propose
    :: MonadAuxxMode m
    => ProtocolMagic
    -> Diffusion m
    -> ProposeUpdateParams
    -> m UpId
propose pm diffusion ProposeUpdateParams{..} = do
    logDebug "Proposing update..."
    skey <- (!! puSecretKeyIdx) <$> getSecretKeysPlain
    updateData <- mapM updateDataElement puUpdates
    let udata = HM.fromList updateData
    skeys <- if not puVoteAll then pure [skey]
             else getSecretKeysPlain
    withSafeSigners skeys (pure emptyPassphrase) $ \ss -> do
        unless (length skeys == length ss) $
            reportFatalError $ "Number of safe signers: " <> show (length ss) <>
                               ", expected " <> show (length skeys)
        let publisherSS = ss !! if not puVoteAll then 0 else puSecretKeyIdx
        let updateProposal =
                mkUpdateProposalWSign
                   pm
                    puBlockVersion
                    puBlockVersionModifier
                    puSoftwareVersion
                    udata
                    def
                    publisherSS
        let upid = hash updateProposal
        submitUpdateProposal pm diffusion ss updateProposal
        if not puVoteAll then
            putText (sformat ("Update proposal submitted, upId: "%hashHexF) upid)
        else
            putText (sformat ("Update proposal submitted along with votes, upId: "%hashHexF) upid)
        return upid
propose
    :: MonadAuxxMode m
    => ProtocolMagic
    -> Diffusion m
    -> ProposeUpdateParams
    -> m UpId
propose pm diffusion ProposeUpdateParams{..} = do
    logDebug "Proposing update..."
    skey <- (!! puSecretKeyIdx) <$> getSecretKeysPlain
    updateData <- mapM updateDataElement puUpdates
    let udata = HM.fromList updateData
    skeys <- if not puVoteAll then pure [skey]
             else getSecretKeysPlain
    withSafeSigners skeys (pure emptyPassphrase) $ \ss -> do
        unless (length skeys == length ss) $
            reportFatalError $ "Number of safe signers: " <> show (length ss) <>
                               ", expected " <> show (length skeys)
        let publisherSS = ss !! if not puVoteAll then 0 else puSecretKeyIdx
        let updateProposal =
                mkUpdateProposalWSign
                   pm
                    puBlockVersion
                    puBlockVersionModifier
                    puSoftwareVersion
                    udata
                    def
                    publisherSS
        let upid = hash updateProposal
        submitUpdateProposal pm diffusion ss updateProposal
        if not puVoteAll then
            putText (sformat ("Update proposal submitted, upId: "%hashHexF) upid)
        else
            putText (sformat ("Update proposal submitted along with votes, upId: "%hashHexF) upid)
        return upid
propose pm diffusion ProposeUpdateParams{..} = do
    logDebug "Proposing update..."
    skey <- (!! puSecretKeyIdx) <$> getSecretKeysPlain
    updateData <- mapM updateDataElement puUpdates
    let udata = HM.fromList updateData
    skeys <- if not puVoteAll then pure [skey]
             else getSecretKeysPlain
    withSafeSigners skeys (pure emptyPassphrase) $ \ss -> do
        unless (length skeys == length ss) $
            reportFatalError $ "Number of safe signers: " <> show (length ss) <>
                               ", expected " <> show (length skeys)
        let publisherSS = ss !! if not puVoteAll then 0 else puSecretKeyIdx
        let updateProposal =
                mkUpdateProposalWSign
                   pm
                    puBlockVersion
                    puBlockVersionModifier
                    puSoftwareVersion
                    udata
                    def
                    publisherSS
        let upid = hash updateProposal
        submitUpdateProposal pm diffusion ss updateProposal
        if not puVoteAll then
            putText (sformat ("Update proposal submitted, upId: "%hashHexF) upid)
        else
            putText (sformat ("Update proposal submitted along with votes, upId: "%hashHexF) upid)
        return upid