cardano-sl-0.4.3: Cardano SL main implementation

Safe HaskellNone
LanguageHaskell2010

Pos.Ssc.GodTossing

Contents

Description

Re-exports of GodTossing modules.

GodTossing is a coin tossing with guaranteed output delivery. Nodes exchange commitments, openings, and shares, and in the end arrive at a shared seed.

See https://eprint.iacr.org/2015/889.pdf (“A Provably Secure Proof-of-Stake Blockchain Protocol”), section 4 for more details.

Synopsis

Documentation

data BadCommAndOpening Source #

Wrapper over '(Commitment, Opening)'. Creates an invalid pair of a Commitment and an Opening w.r.t. verifyOpening.

Constructors

BadCommAndOpening 

newtype BadCommitment Source #

Wrapper over Commitment. Creates an invalid Commitment w.r.t. verifyCommitment.

Constructors

BadComm 

Helpers

genCommitmentAndOpening :: (MonadFail m, MonadIO m) => Threshold -> NonEmpty (AsBinary VssPublicKey) -> m (Commitment, Opening) Source #

Generate securely random SharedSeed.

mkSignedCommitment :: Bi Commitment => SecretKey -> EpochIndex -> Commitment -> SignedCommitment Source #

Make signed commitment from commitment and epoch index using secret key.

secretToSharedSeed :: Secret -> SharedSeed Source #

Convert Secret to SharedSeed.

CommitmentsMap

intersectCommMapWith :: (map -> HashMap StakeholderId x) -> CommitmentsMap -> map -> CommitmentsMap Source #

Generalized version of intersectCommMap which makes it possible to intersect with different maps.

Verification and Checks

checkCertTTL :: EpochIndex -> VssCertificate -> Bool Source #

Check that the VSS certificate has valid TTL: i. e. it is in '[vssMinTTL, vssMaxTTL]'.

verifyCommitmentSignature :: Bi Commitment => EpochIndex -> SignedCommitment -> Bool Source #

Verify signature in SignedCommitment using epoch index.

#checkSig

verifySignedCommitment :: Bi Commitment => EpochIndex -> SignedCommitment -> VerificationRes Source #

Verify SignedCommitment using public key and epoch index.

#verifyCommitmentSignature #verifyCommitment

verifyCommitment :: Commitment -> Bool Source #

Verify that Commitment is correct.

#verifyEncShare

verifyOpening :: Commitment -> Opening -> Bool Source #

Verify that Secret provided with Opening corresponds to given commitment.

#verifySecretProof

Payload and proof

Commitments

data Commitment Source #

Commitment is a message generated during the first stage of GodTossing. It contains encrypted shares and proof of secret. Invariant which must be ensured: commShares is not empty.

type CommitmentSignature = Signature (EpochIndex, Commitment) Source #

Signature which ensures that commitment was generated by node with given public key for given epoch.

Openings

newtype Opening Source #

Opening reveals secret.

Constructors

Opening 

Instances

Eq Opening Source # 

Methods

(==) :: Opening -> Opening -> Bool #

(/=) :: Opening -> Opening -> Bool #

Show Opening Source # 
Generic Opening Source # 

Associated Types

type Rep Opening :: * -> * #

Methods

from :: Opening -> Rep Opening x #

to :: Rep Opening x -> Opening #

NFData Opening Source # 

Methods

rnf :: Opening -> () #

Buildable Opening Source # 

Methods

build :: Opening -> Builder #

type Rep Opening Source # 
type Rep Opening = D1 (MetaData "Opening" "Pos.Ssc.GodTossing.Core.Types" "cardano-sl-0.4.3-Ku3Vny2rTNkDjtuqkt7DM9" True) (C1 (MetaCons "Opening" PrefixI True) (S1 (MetaSel (Just Symbol "getOpening") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (AsBinary Secret))))

Shares

type InnerSharesMap = HashMap StakeholderId (NonEmpty (AsBinary Share)) Source #

Each node generates several SharedSeeds, breaks every SharedSeed into Shares, and sends those encrypted shares to other nodes (for i-th commitment at i-th element of NonEmpty list) In a SharesMap, for each node we collect shares which said node has received and decrypted.

Specifically, if node identified by Address X has received NonEmpty list of shares from node identified by key Y, this NonEmpty list will be at sharesMap ! X ! Y.

Vss certificates

data VssCertificate Source #

VssCertificate allows VssPublicKey to participate in MPC. Each stakeholder should create a Vss keypair, sign VSS public key with signing key and send it into blockchain.

A public key of node is included in certificate in order to enable validation of it using only node's P2PKH address. Expiry epoch is last epoch when certificate is valid, expiry epoch is included in certificate and signature.

Other nodes accept this certificate if it is valid and if node has enough stake.

Invariant: 'checkSig vcSigningKey (vcVssKey, vcExpiryEpoch) vcSignature'.

Instances

Eq VssCertificate Source # 
Ord VssCertificate Source # 
Show VssCertificate Source # 
Generic VssCertificate Source # 

Associated Types

type Rep VssCertificate :: * -> * #

NFData VssCertificate Source # 

Methods

rnf :: VssCertificate -> () #

Buildable VssCertificate Source # 
type Rep VssCertificate Source # 

mkVssCertificate :: SecretKey -> AsBinary VssPublicKey -> EpochIndex -> VssCertificate Source #

Make VssCertificate valid up to given epoch using SecretKey to sign data.

recreateVssCertificate :: MonadFail m => AsBinary VssPublicKey -> EpochIndex -> Signature (AsBinary VssPublicKey, EpochIndex) -> PublicKey -> m VssCertificate Source #

Recreate VssCertificate from its contents. This function main fail if data is invalid.

type VssCertificatesMap = HashMap StakeholderId VssCertificate Source #

VssCertificatesMap contains all valid certificates collected during some period of time.

mkVssCertificatesMap :: [VssCertificate] -> VssCertificatesMap Source #

Safe constructor of VssCertificatesMap. TODO: wrap into newtype.

Payload

data GtPayload Source #

Payload included into blocks.

Instances

Eq GtPayload Source # 
Show GtPayload Source # 
Generic GtPayload Source # 

Associated Types

type Rep GtPayload :: * -> * #

NFData GtPayload Source # 

Methods

rnf :: GtPayload -> () #

type Rep GtPayload Source # 

data GtProof Source #

Proof of GtPayload.

Instances

Eq GtProof Source # 

Methods

(==) :: GtProof -> GtProof -> Bool #

(/=) :: GtProof -> GtProof -> Bool #

Show GtProof Source # 
Generic GtProof Source # 

Associated Types

type Rep GtProof :: * -> * #

Methods

from :: GtProof -> Rep GtProof x #

to :: Rep GtProof x -> GtProof #

NFData GtProof Source # 

Methods

rnf :: GtProof -> () #

type Rep GtProof Source # 

Misc

data SeedError Source #

Data type for error during seed calculation.

Constructors

ExtraOpenings !(HashSet StakeholderId)

Some nodes in the OpeningsMap aren't in the set of participants

ExtraShares !(HashSet StakeholderId)

Some nodes in the SharesMap aren't in the set of participants

NonRichmenParticipants !(HashSet StakeholderId)

Some participants aren't richmen

NotEnoughParticipatingStake !Coin !Coin

There was no majority of stake participating (first parameter – participating stake, second – total richmen stake)

NoSecrets

There were no good secrets so a seed couldn't be generated

BrokenCommitment !StakeholderId

Commitment can't be deserialized or didn't match secret (either recovered or in openings)

NoSecretFound !StakeholderId

Secret couldn't be recovered, or wasn't found in either OpeningsMap or SharesMap

BrokenSecret !StakeholderId

Secret can't be deserialized

BrokenShare !StakeholderId

Share can't be deserialized

CommitmentDistrError !Text

Some errors during computation of commitment distribution

GtPayload

VSS

vssThreshold :: Integral a => a -> Threshold Source #

Figure out the threshold (i.e. how many secret shares would be required to recover each node's secret) using number of participants.

genesisCertificates :: VssCertificatesMap Source #

Certificates in genesis represented as VssCertificatesMap.

'Inv|Req|Data' processing.

sscIsDataUseful :: (WithLogger m, MonadDB m, WithNodeContext kek m, MonadSlots m, MonadSscMem SscGodTossing m) => GtTag -> StakeholderId -> m Bool Source #

Check whether SSC data with given tag and public key can be added to current local data.

sscProcessCommitment :: forall m. GtDataProcessingMode m => SignedCommitment -> m () Source #

Process SignedCommitment received from network, checking it against current state (global + local) and adding to local state if it's valid.

sscProcessOpening :: GtDataProcessingMode m => StakeholderId -> Opening -> m () Source #

Process Opening received from network, checking it against current state (global + local) and adding to local state if it's valid.

sscProcessShares :: GtDataProcessingMode m => StakeholderId -> InnerSharesMap -> m () Source #

Process InnerSharesMap received from network, checking it against current state (global + local) and adding to local state if it's valid.

sscProcessCertificate :: GtDataProcessingMode m => VssCertificate -> m () Source #

Process VssCertificate received from network, checking it against current state (global + local) and adding to local state if it's valid.

Garbage collection worker

localOnNewSlot :: MonadSscMem SscGodTossing m => SlotId -> m () Source #

Clean-up some data when new slot starts. This function is only needed for garbage collection, it doesn't affect validity of local data. Currently it does nothing, but maybe later we'll decide to do clean-up.

Instances

instance SscLocalDataClass SscGodTossing

data GtLocalData Source #

Constructors

GtLocalData 

Fields

getOurCommitment :: MonadDB m => EpochIndex -> m (Maybe SignedCommitment) Source #

Get our commitment for given epoch if it's known.

getOurOpening :: MonadDB m => EpochIndex -> m (Maybe Opening) Source #

Get our opening corresponding for given epoch if it's known.

putOurSecret :: MonadDB m => SignedCommitment -> Opening -> EpochIndex -> m () Source #

Put our secret for given epoch.

calculateSeed Source #

Arguments

:: CommitmentsMap

All participating nodes

-> OpeningsMap

Openings sent by those nodes

-> SharesMap

Decrypted shares

-> RichmenStake

How much stake nodes have

-> Either SeedError SharedSeed 

Calculate SharedSeed. SharedSeed is a random bytestring that all nodes generate together and agree on.

TODO: do we need to check secrets' lengths? Probably not.

Instances

instance SscGStateClass SscGodTossing

getStableCerts :: (MonadSscMem SscGodTossing m, MonadIO m) => EpochIndex -> m VssCertificatesMap Source #

Get stable VSS certificates for given epoch.

Trivial functions

getCommitment :: MonadTossRead m => StakeholderId -> m (Maybe SignedCommitment) Source #

Retrieve SignedCommitment of given stakeholder if it's known.

hasCommitmentToss :: MonadTossRead m => StakeholderId -> m Bool Source #

Check whether there is a SignedCommitment from given stakeholder.

hasOpeningToss :: MonadTossRead m => StakeholderId -> m Bool Source #

Check whether there is an Opening from given stakeholder.

hasSharesToss :: MonadTossRead m => StakeholderId -> m Bool Source #

Check whether there is InnerSharesMap from given stakeholder.

hasCertificateToss :: MonadTossRead m => StakeholderId -> m Bool Source #

Check whether there is VssCertificate from given stakeholder.

Basic logic

getParticipants :: (MonadError TossVerFailure m, MonadToss m) => EpochIndex -> m VssCertificatesMap Source #

Get VssCertificatesMap containing StakeholderIds and VssPublicKeys of participating nodes for given epoch.

computeParticipants :: RichmenSet -> VssCertificatesMap -> VssCertificatesMap Source #

Compute VssCertificates of GodTossing participants using set of richmen and stable certificates.

Payload processing

Helpers

verifyEntriesGuardM :: MonadError TossVerFailure m => (entry -> key) -> (entry -> verificationVal) -> (NonEmpty key -> TossVerFailure) -> (verificationVal -> m Bool) -> [entry] -> m () Source #

class (Monad m, WithLogger m) => MonadTossRead m where Source #

Type class which provides functions necessary for read-only verification of GodTossing data.

Methods

getCommitments :: m CommitmentsMap Source #

Get CommitmentsMap with all commitments.

getOpenings :: m OpeningsMap Source #

Get OpeningsMap with all openings.

getShares :: m SharesMap Source #

Get SharesMap with all shares.

getVssCertificates :: m VssCertificatesMap Source #

Get VssCertificatesMap with all VSS certificates.

getVssCertData :: m VssCertData Source #

getStableCertificates :: EpochIndex -> m VssCertificatesMap Source #

Retrieve all stable VssCertificates for given epoch.

getRichmen :: EpochIndex -> m (Maybe RichmenStake) Source #

Retrieve richmen for given epoch if they are known.

getCommitments :: (MonadTrans t, MonadTossRead m', t m' ~ m) => m CommitmentsMap Source #

Get CommitmentsMap with all commitments.

getOpenings :: (MonadTrans t, MonadTossRead m', t m' ~ m) => m OpeningsMap Source #

Get OpeningsMap with all openings.

getShares :: (MonadTrans t, MonadTossRead m', t m' ~ m) => m SharesMap Source #

Get SharesMap with all shares.

getVssCertData :: (MonadTrans t, MonadTossRead m', t m' ~ m) => m VssCertData Source #

getVssCertificates :: (MonadTrans t, MonadTossRead m', t m' ~ m) => m VssCertificatesMap Source #

Get VssCertificatesMap with all VSS certificates.

getStableCertificates :: (MonadTrans t, MonadTossRead m', t m' ~ m) => EpochIndex -> m VssCertificatesMap Source #

Retrieve all stable VssCertificates for given epoch.

getRichmen :: (MonadTrans t, MonadTossRead m', t m' ~ m) => EpochIndex -> m (Maybe RichmenStake) Source #

Retrieve richmen for given epoch if they are known.

Instances

MonadTossRead PureToss Source # 
MonadTossRead m => MonadTossRead (StateT s m) Source # 
MonadTossRead m => MonadTossRead (ExceptT s m) Source # 
MonadTossRead m => MonadTossRead (ReaderT * s m) Source # 

class MonadTossRead m => MonadToss m where Source #

Type class which provides function necessary for verification of GodTossing data with ability to modify state.

Methods

putCommitment :: SignedCommitment -> m () Source #

Put SignedCommitment into state.

putOpening :: StakeholderId -> Opening -> m () Source #

Put Opening from given stakeholder into state.

putShares :: StakeholderId -> InnerSharesMap -> m () Source #

Put InnerShares from given stakeholder into state.

putCertificate :: VssCertificate -> m () Source #

Put VssCertificate into state.

resetCO :: m () Source #

Reset Commitments and Openings.

resetShares :: m () Source #

Reset Shares.

delCommitment :: StakeholderId -> m () Source #

Delete commitment of given stakeholder.

delOpening :: StakeholderId -> m () Source #

Delete opening of given stakeholder.

delShares :: StakeholderId -> m () Source #

Delete shares of given stakeholder.

setEpochOrSlot :: EpochOrSlot -> m () Source #

This function is called when block with given EpochOrSlot is applied.

putCommitment :: (MonadTrans t, MonadToss m', t m' ~ m) => SignedCommitment -> m () Source #

Put SignedCommitment into state.

putOpening :: (MonadTrans t, MonadToss m', t m' ~ m) => StakeholderId -> Opening -> m () Source #

Put Opening from given stakeholder into state.

putShares :: (MonadTrans t, MonadToss m', t m' ~ m) => StakeholderId -> InnerSharesMap -> m () Source #

Put InnerShares from given stakeholder into state.

putCertificate :: (MonadTrans t, MonadToss m', t m' ~ m) => VssCertificate -> m () Source #

Put VssCertificate into state.

resetCO :: (MonadTrans t, MonadToss m', t m' ~ m) => m () Source #

Reset Commitments and Openings.

resetShares :: (MonadTrans t, MonadToss m', t m' ~ m) => m () Source #

Reset Shares.

delCommitment :: (MonadTrans t, MonadToss m', t m' ~ m) => StakeholderId -> m () Source #

Delete commitment of given stakeholder.

delOpening :: (MonadTrans t, MonadToss m', t m' ~ m) => StakeholderId -> m () Source #

Delete opening of given stakeholder.

delShares :: (MonadTrans t, MonadToss m', t m' ~ m) => StakeholderId -> m () Source #

Delete shares of given stakeholder.

setEpochOrSlot :: (MonadTrans t, MonadToss m', t m' ~ m) => EpochOrSlot -> m () Source #

This function is called when block with given EpochOrSlot is applied.

Instances

MonadToss PureToss Source # 
MonadToss m => MonadToss (StateT s m) Source # 
MonadToss m => MonadToss (ExceptT s m) Source # 
MonadToss m => MonadToss (ReaderT * s m) Source # 

verifyAndApplyGtPayload :: (MonadToss m, MonadError TossVerFailure m) => Either EpochIndex (MainBlockHeader ssc) -> GtPayload -> m () Source #

Verify GtPayload with respect to data provided by MonadToss. If data is valid it is also applied. Otherwise TossVerFailure is thrown using MonadError type class.

applyGenesisBlock :: MonadToss m => EpochIndex -> m () Source #

Apply genesis block for given epoch to Toss state.

rollbackGT :: MonadToss m => EpochOrSlot -> NewestFirst [] GtPayload -> m () Source #

Rollback application of GtPayloads in Toss. First argument is EpochOrSlot of oldest block which is subject to rollback.

normalizeToss :: forall m. MonadToss m => EpochIndex -> TossModifier -> m () Source #

Apply as much data from given TossModifier as possible.

newtype PureToss a Source #

Instances

Monad PureToss Source # 

Methods

(>>=) :: PureToss a -> (a -> PureToss b) -> PureToss b #

(>>) :: PureToss a -> PureToss b -> PureToss b #

return :: a -> PureToss a #

fail :: String -> PureToss a #

Functor PureToss Source # 

Methods

fmap :: (a -> b) -> PureToss a -> PureToss b #

(<$) :: a -> PureToss b -> PureToss a #

Applicative PureToss Source # 

Methods

pure :: a -> PureToss a #

(<*>) :: PureToss (a -> b) -> PureToss a -> PureToss b #

(*>) :: PureToss a -> PureToss b -> PureToss b #

(<*) :: PureToss a -> PureToss b -> PureToss a #

CanLog PureToss Source # 
HasLoggerName PureToss Source # 
MonadToss PureToss Source # 
MonadTossRead PureToss Source # 

type TossT = StateT TossModifier Source #

Monad transformer which stores TossModifier and implements writable MonadToss.

WARNING
This transformer uses StateT and is intended for single-threaded usage only.

evalTossT :: Monad m => TossModifier -> TossT m a -> m a Source #

data GtTag Source #

Tag corresponding to GodTossing data.

Instances

Eq GtTag Source # 

Methods

(==) :: GtTag -> GtTag -> Bool #

(/=) :: GtTag -> GtTag -> Bool #

Show GtTag Source # 

Methods

showsPrec :: Int -> GtTag -> ShowS #

show :: GtTag -> String #

showList :: [GtTag] -> ShowS #

Generic GtTag Source # 

Associated Types

type Rep GtTag :: * -> * #

Methods

from :: GtTag -> Rep GtTag x #

to :: Rep GtTag x -> GtTag #

Buildable GtTag Source # 

Methods

build :: GtTag -> Builder #

type Rep GtTag Source # 
type Rep GtTag = D1 (MetaData "GtTag" "Pos.Ssc.GodTossing.Toss.Types" "cardano-sl-0.4.3-Ku3Vny2rTNkDjtuqkt7DM9" False) ((:+:) ((:+:) (C1 (MetaCons "CommitmentMsg" PrefixI False) U1) (C1 (MetaCons "OpeningMsg" PrefixI False) U1)) ((:+:) (C1 (MetaCons "SharesMsg" PrefixI False) U1) (C1 (MetaCons "VssCertificateMsg" PrefixI False) U1)))

data SscGodTossing Source #

Data type which represents shared seed calculation tag in -XTypeApplication hacks with type families.

Instances

Eq SscGodTossing Source # 
Show SscGodTossing Source # 
Generic SscGodTossing Source # 

Associated Types

type Rep SscGodTossing :: * -> * #

Ssc SscGodTossing Source # 
SscHelpersClass SscGodTossing Source # 
type Rep SscGodTossing Source # 
type Rep SscGodTossing = D1 (MetaData "SscGodTossing" "Pos.Ssc.GodTossing.Type" "cardano-sl-0.4.3-Ku3Vny2rTNkDjtuqkt7DM9" False) V1
type SscLocalData SscGodTossing Source # 
type SscPayload SscGodTossing Source # 
type SscGlobalState SscGodTossing Source # 
type SscProof SscGodTossing Source # 
type SscSeedError SscGodTossing Source # 
type SscNodeContext SscGodTossing Source # 
type SscParams SscGodTossing Source # 
type SscVerifyError SscGodTossing Source # 

Instances

instance Ssc SscGodTossing

data GtTag Source #

Tag corresponding to GodTossing data.

Instances

Eq GtTag Source # 

Methods

(==) :: GtTag -> GtTag -> Bool #

(/=) :: GtTag -> GtTag -> Bool #

Show GtTag Source # 

Methods

showsPrec :: Int -> GtTag -> ShowS #

show :: GtTag -> String #

showList :: [GtTag] -> ShowS #

Generic GtTag Source # 

Associated Types

type Rep GtTag :: * -> * #

Methods

from :: GtTag -> Rep GtTag x #

to :: Rep GtTag x -> GtTag #

Buildable GtTag Source # 

Methods

build :: GtTag -> Builder #

type Rep GtTag Source # 
type Rep GtTag = D1 (MetaData "GtTag" "Pos.Ssc.GodTossing.Toss.Types" "cardano-sl-0.4.3-Ku3Vny2rTNkDjtuqkt7DM9" False) ((:+:) ((:+:) (C1 (MetaCons "CommitmentMsg" PrefixI False) U1) (C1 (MetaCons "OpeningMsg" PrefixI False) U1)) ((:+:) (C1 (MetaCons "SharesMsg" PrefixI False) U1) (C1 (MetaCons "VssCertificateMsg" PrefixI False) U1)))

data GtMsgContents Source #

Data message. Can be used to send actual data.

Instances

Eq GtMsgContents Source # 
Show GtMsgContents Source # 
Generic GtMsgContents Source # 

Associated Types

type Rep GtMsgContents :: * -> * #

Buildable GtMsgContents Source # 
type Rep GtMsgContents Source # 
type LimitType (DataMsg GtMsgContents) # 

msgContentsTag :: GtMsgContents -> GtTag Source #

GtTag appropriate for given DataMsg.

Instance types

data GtGlobalState Source #

Global state of GodTossing, contains relevant SSC data from blocks.

Constructors

GtGlobalState 

Fields

data GtContext Source #

Constructors

GtContext 

Fields

data GtParams Source #

Constructors

GtParams 

Fields

data GtSecretStorage Source #

Constructors

GtSecretStorage 

Fields

Lenses

GtPayload

data VssCertData Source #

Wrapper around VssCertificate with TTL. Every VssCertificate has own TTL. Wrapper supports simple HashMap operations. Wrapper holds VssCertificatesMap and Set of certificates sorted by expiry epoch.

Constructors

VssCertData 

Fields

insert :: VssCertificate -> VssCertData -> VssCertData Source #

Remove old certificate corresponding to the specified StakeholderId and insert new certificate.

lookup :: StakeholderId -> VssCertData -> Maybe VssCertificate Source #

Lookup certificate corresponding to the specified StakeholderId.

lookupExpiryEpoch :: StakeholderId -> VssCertData -> Maybe EpochIndex Source #

Lookup expiry epoch of certificate corresponding to the specified StakeholderId.

setLastKnownEoS :: EpochOrSlot -> VssCertData -> VssCertData Source #

Set last known slot (lks). 1. If new lks is bigger than lastKnownEoS then some expired certificates will be removed. 2. If new lks is less than lastKnownEoS then some inserted after nlks certificates will be removed (and whenExpire) also will be updated.

keys :: VssCertData -> [StakeholderId] Source #

Ids of stakeholders issued certificates.

member :: StakeholderId -> VssCertData -> Bool Source #

Return True if the specified address hash is present in the map, False otherwise.

expiryEpoch :: VssCertificate -> EpochIndex Source #

Convert expiry epoch of certificate to FlatSlotId.

Functions which delete certificates. Be careful

delete :: StakeholderId -> VssCertData -> VssCertData Source #

Delete certificate corresponding to the specified StakeholderId. This function is dangerous, because after using it you can't rollback deleted certificates. Use carefully.

difference :: VssCertData -> HashMap StakeholderId a -> VssCertData Source #

This function is dangerous, because after you using it you can't rollback deleted certificates. Use carefully.

filter :: (StakeholderId -> Bool) -> VssCertData -> VssCertData Source #

Filtering the certificates. This function is dangerous, because after you using it you can't rollback deleted certificates. Use carefully.