Skip to content

Commit

Permalink
Merge pull request #652 from IntersectMBO/smelc/extend-key-verificati…
Browse files Browse the repository at this point in the history
…on-key

verification-key: support DRep keys as well as committee keys, extended or not
  • Loading branch information
smelc authored Mar 19, 2024
2 parents 0b18245 + 2b374d0 commit 149940e
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 47 deletions.
2 changes: 2 additions & 0 deletions cardano-cli/cardano-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ test-suite cardano-cli-test
, filepath
, hedgehog
, hedgehog-extras ^>= 0.6.1.0
, exceptions
, tasty
, tasty-hedgehog
, text
Expand All @@ -313,6 +314,7 @@ test-suite cardano-cli-test
Test.Cli.Pioneers.Exercise5
Test.Cli.Pioneers.Exercise6
Test.Cli.Pipes
Test.Cli.VerificationKey
Test.Cli.Shelley.Run.Query

ghc-options: -threaded -rtsopts "-with-rtsopts=-N -T"
Expand Down
2 changes: 2 additions & 0 deletions cardano-cli/src/Cardano/CLI/Read.hs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ readWitnessSigningData (KeyWitnessSigningData skFile mbByronAddr) = do
-- A Byron address should only be specified along with a Byron signing key.
Left ReadWitnessSigningDataSigningKeyAndAddressMismatch
where
-- If you update these variables, consider updating the ones with the same
-- names in Cardano.CLI.Types.Key
textEnvFileTypes =
[ FromSomeType (AsSigningKey AsByronKey ) (`AByronSigningWitness` mbByronAddr)
, FromSomeType (AsSigningKey AsPaymentKey ) APaymentSigningWitness
Expand Down
82 changes: 41 additions & 41 deletions cardano-cli/src/Cardano/CLI/Types/Key.hs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ data SomeSigningKey
| AGenesisDelegateSigningKey (SigningKey GenesisDelegateKey)
| AGenesisDelegateExtendedSigningKey (SigningKey GenesisDelegateExtendedKey)
| AGenesisUTxOSigningKey (SigningKey GenesisUTxOKey)
| ADRepSigningKey (SigningKey DRepKey)
| ADRepExtendedSigningKey (SigningKey DRepExtendedKey)
| ACommitteeColdSigningKey (SigningKey CommitteeColdKey)
| ACommitteeColdExtendedSigningKey (SigningKey CommitteeColdExtendedKey)
| ACommitteeHotSigningKey (SigningKey CommitteeHotKey)
| ACommitteeHotExtendedSigningKey (SigningKey CommitteeHotExtendedKey)
| AVrfSigningKey (SigningKey VrfKey)
| AKesSigningKey (SigningKey KesKey)

Expand All @@ -375,6 +381,12 @@ withSomeSigningKey ssk f =
AGenesisDelegateSigningKey sk -> f sk
AGenesisDelegateExtendedSigningKey sk -> f sk
AGenesisUTxOSigningKey sk -> f sk
ADRepSigningKey sk -> f sk
ADRepExtendedSigningKey sk -> f sk
ACommitteeColdSigningKey sk -> f sk
ACommitteeColdExtendedSigningKey sk -> f sk
ACommitteeHotSigningKey sk -> f sk
ACommitteeHotExtendedSigningKey sk -> f sk
AVrfSigningKey sk -> f sk
AKesSigningKey sk -> f sk

Expand All @@ -385,48 +397,36 @@ readSigningKeyFile skFile =
newExceptT $
readKeyFileAnyOf bech32FileTypes textEnvFileTypes skFile
where
-- If you update these variables, consider updating the ones with the same
-- names in Cardano.CLI.Read
textEnvFileTypes =
[ FromSomeType (AsSigningKey AsByronKey)
AByronSigningKey
, FromSomeType (AsSigningKey AsPaymentKey)
APaymentSigningKey
, FromSomeType (AsSigningKey AsPaymentExtendedKey)
APaymentExtendedSigningKey
, FromSomeType (AsSigningKey AsStakeKey)
AStakeSigningKey
, FromSomeType (AsSigningKey AsStakeExtendedKey)
AStakeExtendedSigningKey
, FromSomeType (AsSigningKey AsStakePoolKey)
AStakePoolSigningKey
, FromSomeType (AsSigningKey AsGenesisKey)
AGenesisSigningKey
, FromSomeType (AsSigningKey AsGenesisExtendedKey)
AGenesisExtendedSigningKey
, FromSomeType (AsSigningKey AsGenesisDelegateKey)
AGenesisDelegateSigningKey
, FromSomeType (AsSigningKey AsGenesisDelegateExtendedKey)
AGenesisDelegateExtendedSigningKey
, FromSomeType (AsSigningKey AsGenesisUTxOKey)
AGenesisUTxOSigningKey
, FromSomeType (AsSigningKey AsVrfKey)
AVrfSigningKey
, FromSomeType (AsSigningKey AsKesKey)
AKesSigningKey
[ FromSomeType (AsSigningKey AsByronKey) AByronSigningKey
, FromSomeType (AsSigningKey AsPaymentKey) APaymentSigningKey
, FromSomeType (AsSigningKey AsPaymentExtendedKey) APaymentExtendedSigningKey
, FromSomeType (AsSigningKey AsStakeKey) AStakeSigningKey
, FromSomeType (AsSigningKey AsStakeExtendedKey) AStakeExtendedSigningKey
, FromSomeType (AsSigningKey AsStakePoolKey) AStakePoolSigningKey
, FromSomeType (AsSigningKey AsGenesisKey) AGenesisSigningKey
, FromSomeType (AsSigningKey AsGenesisExtendedKey) AGenesisExtendedSigningKey
, FromSomeType (AsSigningKey AsGenesisDelegateKey) AGenesisDelegateSigningKey
, FromSomeType (AsSigningKey AsGenesisDelegateExtendedKey) AGenesisDelegateExtendedSigningKey
, FromSomeType (AsSigningKey AsGenesisUTxOKey) AGenesisUTxOSigningKey
, FromSomeType (AsSigningKey AsDRepKey) ADRepSigningKey
, FromSomeType (AsSigningKey AsDRepExtendedKey) ADRepExtendedSigningKey
, FromSomeType (AsSigningKey AsCommitteeColdKey) ACommitteeColdSigningKey
, FromSomeType (AsSigningKey AsCommitteeColdExtendedKey) ACommitteeColdExtendedSigningKey
, FromSomeType (AsSigningKey AsCommitteeHotKey) ACommitteeHotSigningKey
, FromSomeType (AsSigningKey AsCommitteeHotExtendedKey) ACommitteeHotExtendedSigningKey
, FromSomeType (AsSigningKey AsVrfKey) AVrfSigningKey
, FromSomeType (AsSigningKey AsKesKey) AKesSigningKey
]

bech32FileTypes =
[ FromSomeType (AsSigningKey AsPaymentKey)
APaymentSigningKey
, FromSomeType (AsSigningKey AsPaymentExtendedKey)
APaymentExtendedSigningKey
, FromSomeType (AsSigningKey AsStakeKey)
AStakeSigningKey
, FromSomeType (AsSigningKey AsStakeExtendedKey)
AStakeExtendedSigningKey
, FromSomeType (AsSigningKey AsStakePoolKey)
AStakePoolSigningKey
, FromSomeType (AsSigningKey AsVrfKey)
AVrfSigningKey
, FromSomeType (AsSigningKey AsKesKey)
AKesSigningKey
]
[ FromSomeType (AsSigningKey AsPaymentKey) APaymentSigningKey
, FromSomeType (AsSigningKey AsPaymentExtendedKey) APaymentExtendedSigningKey
, FromSomeType (AsSigningKey AsStakeKey) AStakeSigningKey
, FromSomeType (AsSigningKey AsStakeExtendedKey) AStakeExtendedSigningKey
, FromSomeType (AsSigningKey AsStakePoolKey) AStakePoolSigningKey
, FromSomeType (AsSigningKey AsVrfKey) AVrfSigningKey
, FromSomeType (AsSigningKey AsKesKey) AKesSigningKey
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

module Test.Golden.Governance.Committee where

import Control.Monad (void)
import Control.Monad (forM_, void)
import Text.Regex.TDFA ((=~))

import Test.Cardano.CLI.Util
Expand Down Expand Up @@ -220,4 +220,29 @@ hprop_golden_governance_committee_hot_extended_key_signing =
, "--out-file", outFile
]

H.diffFileVsGoldenFile outFile outGold
H.diffFileVsGoldenFile outFile outGold

-- | Execute me with:
-- @cabal test cardano-cli-golden --test-options '-p "/golden verification key committee/"'@
hprop_golden_verification_key_committee :: Property
hprop_golden_verification_key_committee = do
let values = [ ( "test/cardano-cli-golden/files/input/governance/committee/cc.extended.hot.skey"
, "test/cardano-cli-golden/files/golden/governance/committee/cc.extended.hot.vkey"
)
,
( "test/cardano-cli-golden/files/input/governance/committee/cc.extended.cold.skey"
, "test/cardano-cli-golden/files/golden/governance/committee/cc.extended.cold.vkey"
)
]

propertyOnce $ forM_ values $ \(skeyFile, vkeyGolden) ->
H.moduleWorkspace "tmp" $ \tempDir -> do
vkeyFileOut <- noteTempFile tempDir "cc.extended.vkey"

H.noteM_ $ execCardanoCLI
[ "conway", "key", "verification-key"
, "--signing-key-file", skeyFile
, "--verification-key-file", vkeyFileOut
]

H.diffFileVsGoldenFile vkeyFileOut vkeyGolden
22 changes: 20 additions & 2 deletions cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/DRep.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import Numeric (showOct)
import System.Posix.Files (fileMode, getFileStatus)
#endif

import Test.Cardano.CLI.Util (FileSem, bracketSem, execCardanoCLI, noteInputFile, noteTempFile, propertyOnce, newFileSem)
import Test.Cardano.CLI.Util (FileSem, bracketSem, execCardanoCLI, newFileSem,
noteInputFile, noteTempFile, propertyOnce)

import Hedgehog
import qualified Hedgehog as H
Expand Down Expand Up @@ -105,7 +106,7 @@ hprop_golden_governance_drep_extended_key_signing =
outFile <- H.noteTempFile tempDir "outFile"
outGold <- H.note "test/cardano-cli-golden/files/golden/governance/drep/extended-key-signing/tx.signed"

void $ execCardanoCLI
H.noteShowM_ $ execCardanoCLI
[ "conway", "transaction", "sign"
, "--tx-body-file", txBody
, "--signing-key-file", skeyFile
Expand Down Expand Up @@ -276,3 +277,20 @@ hprop_golden_governance_drep_update_certificate_vkey_file = propertyOnce . H.mod
]

H.diffFileVsGoldenFile outFile goldenFile

-- | Execute me with:
-- @cabal test cardano-cli-golden --test-options '-p "/golden verification key drep/"'@
hprop_golden_verification_key_drep :: Property
hprop_golden_verification_key_drep =
propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> do
skeyFile <- noteInputFile "test/cardano-cli-golden/files/input/governance/drep/extended-key-signing/drep.skey"
vkeyFileOut <- noteTempFile tempDir "drep.extended.vkey"
goldenFile <- H.note "test/cardano-cli-golden/files/golden/governance/drep/drep-extended.vkey.out"

H.noteShowM_ $ execCardanoCLI
[ "conway", "key", "verification-key"
, "--signing-key-file", skeyFile
, "--verification-key-file", vkeyFileOut
]

H.diffFileVsGoldenFile vkeyFileOut goldenFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "ConstitutionalCommitteeColdExtendedVerificationKey_ed25519_bip32",
"description": "",
"cborHex": "58400a9d35aa5299580a67b1e43a3a4b6d43ef29c94e56c51ce4c17e9a53c1d0f39aa7f68837c38ef680b2dc8f047581707a32f6fcade23d4e02177d389002484798"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "ConstitutionalCommitteeHotExtendedVerificationKey_ed25519_bip32",
"description": "",
"cborHex": "5840f010c4332699c6ea1e43b427919860277169382d43d2969b28a110cfa08d955c4f178f20955541ce918a6a1352c32536f22677008f9f918d109663e4d2bdc084"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "DRepExtendedVerificationKey_ed25519_bip32",
"description": "",
"cborHex": "5840b18eacea2003b68e39137545e9d42ce5bca133ca0334d6a75aa9cb1fd02be7ec90e91f5357e2c68949f0f09717c5b9809b6a74d5f87ea35383c82841f2357564"
}
47 changes: 45 additions & 2 deletions cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Aeson.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{-# LANGUAGE TypeApplications #-}

module Test.Cardano.CLI.Aeson (
assertHasKeys,
assertHasMappings,
assertEqualModuloDesc
, assertHasKeys
, assertHasMappings
) where

import Control.Monad (forM_)
Expand Down Expand Up @@ -118,3 +121,43 @@ assertHasMapping file obj key value = GHC.withFrozenCallStack $ do
H.failure


-- | @assertEqualModuloDesc file1 file2@ loads @file1@ and @file2@ from disk,
-- then it strips the field @description@ from the loaded content, and finally compare
-- the two values. The values must be equal, otherwise the test is failed.
--
-- Required, because command @"key" "verification-key"@ generates keys without descriptions.
-- Note that it would be better to write descriptions, see:
-- https://github.com/IntersectMBO/cardano-cli/issues/429#issuecomment-2003880575
assertEqualModuloDesc :: ()
=> (HasCallStack, MonadIO m, MonadTest m)
=> FilePath -- ^ The file of the first generated verification key
-> FilePath -- ^ The file of the second generated verification key, i.e. the one
-- generated by calling "key verification-key"
-> m ()
assertEqualModuloDesc file1 file2 = GHC.withFrozenCallStack $ do
value1 <- H.readJsonFileOk @Value file1
value1' <- removeDescription value1

value2 <- H.readJsonFileOk @Value file2
value2' <- removeDescription value2

value1' H.=== value2'

-- | Removes the @description@ field from a JSON object.
removeDescription :: ()
=> (HasCallStack, MonadTest m)
=> Value
-> m Value
removeDescription v =
case v of
Object inner ->
return $ Object $ Aeson.KeyMap.delete (Aeson.fromText "description") inner
Array _ -> failWrongType "array"
Number _ -> failWrongType "number"
Bool _ -> failWrongType "bool"
String _ -> failWrongType "string"
Null -> failWrongType "null"
where
failWrongType got = do
H.note_ $ "Expected object but got: " <> got
H.failure
57 changes: 57 additions & 0 deletions cardano-cli/test/cardano-cli-test/Test/Cli/VerificationKey.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
-- | Tests of the command "key verification-key", in particular tests of
-- https://github.com/IntersectMBO/cardano-cli/issues/651
module Test.Cli.VerificationKey where

import Control.Monad.Catch (MonadCatch)
import Control.Monad.IO.Class (MonadIO)
import GHC.Stack (HasCallStack)
import qualified GHC.Stack as GHC

import Test.Cardano.CLI.Aeson (assertEqualModuloDesc)
import Test.Cardano.CLI.Util

import Hedgehog (MonadTest, Property)
import qualified Hedgehog.Extras.Test.Base as H

-- | Execute me with:
-- @cabal test cardano-cli-test --test-options '-p "/verification key drep/"'@
hprop_verification_key_drep :: Property
hprop_verification_key_drep =
propertyOnce . H.moduleWorkspace "tmp" $ runOne ["drep", "key-gen"]

-- | Execute me with:
-- @cabal test cardano-cli-test --test-options '-p "/verification key committee hot/"'@
hprop_verification_key_committee_hot :: Property
hprop_verification_key_committee_hot =
propertyOnce . H.moduleWorkspace "tmp" $ runOne ["committee", "key-gen-hot"]

-- | Execute me with:
-- @cabal test cardano-cli-test --test-options '-p "/verification key committee cold/"'@
hprop_verification_key_committee_cold :: Property
hprop_verification_key_committee_cold =
propertyOnce . H.moduleWorkspace "tmp" $ runOne ["committee", "key-gen-cold"]

runOne :: ()
=> (HasCallStack, MonadCatch m, MonadIO m, MonadTest m)
=> [String] -- ^ The piece of the command to generate the keys
-> FilePath -- ^ The temporary directory, i.e. where the test is allowed to generate files
-> m ()
runOne cmd tempDir = GHC.withFrozenCallStack $ do
verificationKeyFile <- noteTempFile tempDir "gen.vkey"
signingKeyFile <- noteTempFile tempDir "gen.skey"
verificationKeyFileOut <- noteTempFile tempDir "vkey.out"

H.noteM_ $ execCardanoCLI $
[ "conway", "governance" ]
++ cmd ++
[ "--verification-key-file", verificationKeyFile
, "--signing-key-file", signingKeyFile
]

H.noteM_ $ execCardanoCLI
[ "conway", "key", "verification-key"
, "--signing-key-file", signingKeyFile
, "--verification-key-file", verificationKeyFileOut
]

assertEqualModuloDesc verificationKeyFile verificationKeyFileOut

0 comments on commit 149940e

Please sign in to comment.