diff --git a/.changes/20260813_120000_cardano-api_sebastian.nagel_stake_pool_bls_key.yml b/.changes/20260813_120000_cardano-api_sebastian.nagel_stake_pool_bls_key.yml new file mode 100644 index 0000000000..8b44feff52 --- /dev/null +++ b/.changes/20260813_120000_cardano-api_sebastian.nagel_stake_pool_bls_key.yml @@ -0,0 +1,7 @@ +description: | + Added `stakePoolBlsKey :: Maybe Ledger.BlsKey` to `StakePoolParameters`, wired to the ledger's `sppBlsKey` in `toShelleyPoolParams`/`fromShelleyPoolParams`. This is a BLS voting key plus its proof of possession, registrable from the Dijkstra era onwards; `Nothing` for a pool that does not vote. Callers constructing `StakePoolParameters` need to set the new field. Also added `createBlsKeyRegistration :: SigningKey BlsKey -> Ledger.BlsKey`, which derives the verification key and proof of possession from a BLS signing key, and re-exported the ledger's `BlsKey` from `Cardano.Api.Ledger`. +kind: + - feature + - breaking +pr: 0 +project: cardano-api diff --git a/cardano-api/cardano-api.cabal b/cardano-api/cardano-api.cabal index e1ea28870c..078a4bef27 100644 --- a/cardano-api/cardano-api.cabal +++ b/cardano-api/cardano-api.cabal @@ -146,7 +146,7 @@ library cardano-ledger-binary >=1.6, cardano-ledger-byron >=1.2, cardano-ledger-conway >=1.19, - cardano-ledger-core >=1.20, + cardano-ledger-core >=1.22, cardano-ledger-dijkstra >=0.1, cardano-ledger-mary >=1.8, cardano-ledger-shelley >=1.16, diff --git a/cardano-api/src/Cardano/Api/Certificate/Internal.hs b/cardano-api/src/Cardano/Api/Certificate/Internal.hs index 54530aed14..d709deea98 100644 --- a/cardano-api/src/Cardano/Api/Certificate/Internal.hs +++ b/cardano-api/src/Cardano/Api/Certificate/Internal.hs @@ -50,6 +50,9 @@ data StakePoolParameters = StakePoolParameters { stakePoolId :: PoolId , stakePoolVRF :: Hash VrfKey + , stakePoolBlsKey :: Maybe Ledger.BlsKey + -- ^ The pool's BLS voting key and its proof of possession. Only registrable + -- from the Dijkstra era onwards; 'Nothing' for a pool that does not vote. , stakePoolCost :: L.Coin , stakePoolMargin :: Rational , stakePoolRewardAccount :: StakeAddress @@ -91,6 +94,7 @@ toShelleyPoolParams StakePoolParameters { stakePoolId = StakePoolKeyHash poolkh , stakePoolVRF = VrfKeyHash vrfkh + , stakePoolBlsKey , stakePoolCost , stakePoolMargin , stakePoolRewardAccount @@ -120,6 +124,7 @@ toShelleyPoolParams , Ledger.sppMetadata = toShelleyPoolMetadata <$> Ledger.maybeToStrictMaybe stakePoolMetadata + , Ledger.sppBlsKey = Ledger.maybeToStrictMaybe stakePoolBlsKey } where toShelleyStakePoolRelay :: StakePoolRelay -> Ledger.StakePoolRelay @@ -172,10 +177,12 @@ fromShelleyPoolParams , Ledger.sppOwners , Ledger.sppRelays , Ledger.sppMetadata + , Ledger.sppBlsKey } = StakePoolParameters { stakePoolId = StakePoolKeyHash sppId , stakePoolVRF = VrfKeyHash (Ledger.fromVRFVerKeyHash sppVrf) + , stakePoolBlsKey = Ledger.strictMaybeToMaybe sppBlsKey , stakePoolCost = sppCost , stakePoolMargin = Ledger.unboundRational sppMargin , stakePoolRewardAccount = fromShelleyStakeAddr sppAccountAddress diff --git a/cardano-api/src/Cardano/Api/Key.hs b/cardano-api/src/Cardano/Api/Key.hs index e3a03ea7fb..4494d61494 100644 --- a/cardano-api/src/Cardano/Api/Key.hs +++ b/cardano-api/src/Cardano/Api/Key.hs @@ -75,6 +75,7 @@ module Cardano.Api.Key , BlsPossessionProof , blsPossessionProof , createBlsPossessionProof + , createBlsKeyRegistration -- ** Type proxy , HasTypeProxy (..) diff --git a/cardano-api/src/Cardano/Api/Key/Internal/Leios.hs b/cardano-api/src/Cardano/Api/Key/Internal/Leios.hs index dd7cc93f48..4552993cdd 100644 --- a/cardano-api/src/Cardano/Api/Key/Internal/Leios.hs +++ b/cardano-api/src/Cardano/Api/Key/Internal/Leios.hs @@ -22,6 +22,9 @@ module Cardano.Api.Key.Internal.Leios , BlsPossessionProof , blsPossessionProof , createBlsPossessionProof + + -- * Registration + , createBlsKeyRegistration ) where @@ -40,6 +43,9 @@ import Cardano.Crypto.DSIGN.BLS12381 qualified as Crypto import Cardano.Crypto.DSIGN.Class qualified as Crypto import Cardano.Crypto.Hash.Class qualified as Crypto import Cardano.Ledger.Hashes (HASH) +-- Qualified: the ledger's 'BlsKey' record and its 'blsPossessionProof' field +-- both clash with names this module already defines. +import Cardano.Ledger.State qualified as Ledger import Data.ByteString (ByteString) import Data.Either.Combinators (maybeToRight) @@ -216,3 +222,15 @@ instance HasTextEnvelope BlsPossessionProof where textEnvelopeDefaultDescr :: BlsPossessionProof -> TextEnvelopeDescr textEnvelopeDefaultDescr _ = "BLS12-381 possession proof" + +-- | Derive everything a stake pool has to register for the voting scheme: its +-- BLS verification key plus a proof of possession for it. +createBlsKeyRegistration :: SigningKey BlsKey -> Ledger.BlsKey +createBlsKeyRegistration skey = + Ledger.BlsKey + { Ledger.blsPubKey = vkey + , Ledger.blsPossessionProof = proof + } + where + BlsVerificationKey vkey = getVerificationKey skey + BlsPossessionProof proof = createBlsPossessionProof skey diff --git a/cardano-api/src/Cardano/Api/Ledger/Internal/Reexport.hs b/cardano-api/src/Cardano/Api/Ledger/Internal/Reexport.hs index 2b6ce58c43..b38d4fb98f 100644 --- a/cardano-api/src/Cardano/Api/Ledger/Internal/Reexport.hs +++ b/cardano-api/src/Cardano/Api/Ledger/Internal/Reexport.hs @@ -19,6 +19,7 @@ module Cardano.Api.Ledger.Internal.Reexport , fromVRFVerKeyHash , toVRFVerKeyHash , StakePoolParams (..) + , BlsKey (..) , HasKeyRole , MIRPot (..) , MIRTarget (..) @@ -414,7 +415,8 @@ import Cardano.Ledger.Shelley.TxCert , ShelleyTxCert (..) ) import Cardano.Ledger.State - ( PoolMetadata (..) + ( BlsKey (..) + , PoolMetadata (..) , ScriptsNeeded , StakePoolParams (..) , StakePoolRelay (..)