<commit_before>-- | Generation of genesis data for testnet.

module Dump
       ( dumpRichSecrets
       , dumpFakeAvvmSeed
       , dumpGeneratedGenesisData
       ) where

import           Universum

import           Control.Lens           ((?~))
import           Crypto.Random          (MonadRandom)
import qualified Data.Text              as T
import qualified Serokell.Util.Base64   as B64
import           System.Directory       (createDirectoryIfMissing)
import           System.FilePath        ((</>))
import           System.Wlog            (WithLogger, logInfo)

import           Pos.Core.Configuration (HasGeneratedSecrets, generatedSecrets)
import           Pos.Core.Genesis       (GeneratedSecrets (..), RichSecrets (..))
import           Pos.Crypto             (EncryptedSecretKey)
import           Pos.Util.UserSecret    (UserSecret, initializeUserSecret,
                                         mkGenesisWalletUserSecret, takeUserSecret,
                                         usKeys, usPrimKey, usVss, usWallet,
                                         writeUserSecretRelease)

----------------------------------------------------------------------------
-- Dump individual secrets
----------------------------------------------------------------------------

dumpRichSecrets
    :: (MonadIO m, MonadThrow m, WithLogger m, MonadRandom m)
    => FilePath
    -> RichSecrets
    -> m ()
dumpRichSecrets fp RichSecrets {..} =
    dumpUserSecret fp $
    foldl' (.) identity [ usPrimKey .~ Just rsPrimaryKey
                        , usVss .~ Just rsVssKeyPair
                        ]

dumpPoorSecret
    :: (MonadIO m, MonadThrow m, WithLogger m, MonadRandom m)
    => FilePath
    -> EncryptedSecretKey
    -> m ()
dumpPoorSecret fp hdwSk =
    dumpUserSecret fp $
    foldl' (.) identity [ usKeys %~ (hdwSk :)
                        , usWallet ?~ mkGenesisWalletUserSecret hdwSk
                        ]

dumpFakeAvvmSeed :: MonadIO m => FilePath -> ByteString -> m ()
dumpFakeAvvmSeed fp seed = writeFile fp (B64.encode seed)

----------------------------------------------------------------------------
-- Dump all generated secrets
----------------------------------------------------------------------------

dumpGeneratedGenesisData
    :: (MonadIO m, WithLogger m, MonadThrow m, MonadRandom m, HasGeneratedSecrets)
    => (FilePath, FilePath)
    -> m ()
dumpGeneratedGenesisData (dir, pat) = do
    let GeneratedSecrets {..} =
            fromMaybe (error "GeneratedSecrets are unknown") generatedSecrets
    dumpKeyfiles (dir, pat) gsRichSecrets gsPoorSecrets
    dumpFakeAvvmSeeds dir gsFakeAvvmSeeds

dumpKeyfiles
    :: (MonadIO m, MonadThrow m, WithLogger m, MonadRandom m)
    => (FilePath, FilePath) -- directory and key-file pattern
    -> [RichSecrets]
    -> [EncryptedSecretKey]
    -> m ()
dumpKeyfiles (dir, pat) richs poors = do
    let keysDir = dir </> "generated-keys"
    let richDir = keysDir </> "rich"
    let poorDir = keysDir </> "poor"
    logInfo $ "Dumping generated genesis secrets into " <> fromString keysDir
    liftIO $ createDirectoryIfMissing True richDir
    liftIO $ createDirectoryIfMissing True poorDir

    let totalSecrets = length richs + length poors

    let patternize = applyPattern @Int pat
    forM_ (zip richs [1 .. ]) $ \(richSecrets, i) ->
        dumpRichSecrets (richDir </> patternize i) richSecrets
    forM_ (zip poors [1 .. ]) $ \(hdwSk, i) ->
        dumpPoorSecret (poorDir </> patternize i) hdwSk

    logInfo $ show totalSecrets <> " keyfiles are generated"

dumpFakeAvvmSeeds
    :: (MonadIO m, WithLogger m)
    => FilePath
    -> [ByteString]
    -> m ()
dumpFakeAvvmSeeds dir seeds = do
    let keysDir = dir </> "keys-fakeavvm"
    logInfo $ "Generating fake avvm data into " <> fromString keysDir
    liftIO $ createDirectoryIfMissing True keysDir
    let faoCount = length seeds

    forM_ (zip seeds [1 .. faoCount]) $ \(seed, i) ->
        dumpFakeAvvmSeed (keysDir </> ("fake-" <> show i <> ".seed")) seed

    logInfo (show faoCount <> " fake avvm seeds are generated")

----------------------------------------------------------------------------
-- Helpers
----------------------------------------------------------------------------

dumpUserSecret
    :: (MonadIO m, MonadThrow m, WithLogger m, MonadRandom m)
    => FilePath
    -> (UserSecret -> UserSecret)
    -> m ()
dumpUserSecret fp operation = do
    initializeUserSecret fp
    us <- takeUserSecret fp
    writeUserSecretRelease (operation us)

-- Replace "{}" with the result of applying 'show' to the given
-- value.
applyPattern :: Show a => FilePath -> a -> FilePath
applyPattern fp a = replace "{}" (show a) fp
  where
    replace :: FilePath -> FilePath -> FilePath -> FilePath
    replace x b = toString . (T.replace `on` toText) x b . toText<commit_msg>[CSL-1807] Extend cardano-keygen to dump delegation issuers' keys<commit_after>-- | Generation of genesis data for testnet.

module Dump
       ( dumpRichSecrets
       , dumpFakeAvvmSeed
       , dumpGeneratedGenesisData
       ) where

import           Universum

import           Control.Lens           ((?~))
import qualified Data.Text              as T
import           Serokell.Util          (enumerate)
import qualified Serokell.Util.Base64   as B64
import           System.Directory       (createDirectoryIfMissing)
import           System.FilePath        ((</>))
import           System.Wlog            (WithLogger, logInfo)

import           Pos.Core.Configuration (HasGeneratedSecrets, generatedSecrets)
import           Pos.Core.Genesis       (GeneratedSecrets (..), RichSecrets (..))
import           Pos.Crypto             (EncryptedSecretKey, SecretKey)
import           Pos.Util.UserSecret    (UserSecret, initializeUserSecret,
                                         mkGenesisWalletUserSecret, takeUserSecret,
                                         usKeys, usPrimKey, usVss, usWallet,
                                         writeUserSecretRelease)

----------------------------------------------------------------------------
-- Dump individual secrets
----------------------------------------------------------------------------

dumpDlgIssuerSecret
    :: (MonadIO m, MonadThrow m, WithLogger m)
    => FilePath
    -> SecretKey
    -> m ()
dumpDlgIssuerSecret fp sk = dumpUserSecret fp $ usPrimKey .~ Just sk

dumpRichSecrets
    :: (MonadIO m, MonadThrow m, WithLogger m)
    => FilePath
    -> RichSecrets
    -> m ()
dumpRichSecrets fp RichSecrets {..} =
    dumpUserSecret fp $
    foldl' (.) identity [ usPrimKey .~ Just rsPrimaryKey
                        , usVss .~ Just rsVssKeyPair
                        ]

dumpPoorSecret
    :: (MonadIO m, MonadThrow m, WithLogger m)
    => FilePath
    -> EncryptedSecretKey
    -> m ()
dumpPoorSecret fp hdwSk =
    dumpUserSecret fp $
    foldl' (.) identity [ usKeys %~ (hdwSk :)
                        , usWallet ?~ mkGenesisWalletUserSecret hdwSk
                        ]

dumpFakeAvvmSeed :: MonadIO m => FilePath -> ByteString -> m ()
dumpFakeAvvmSeed fp seed = writeFile fp (B64.encode seed)

----------------------------------------------------------------------------
-- Dump all generated secrets
----------------------------------------------------------------------------

dumpGeneratedGenesisData
    :: (MonadIO m, WithLogger m, MonadThrow m, HasGeneratedSecrets)
    => (FilePath, FilePath)
    -> m ()
dumpGeneratedGenesisData (dir, pat) = do
    let GeneratedSecrets {..} =
            fromMaybe (error "GeneratedSecrets are unknown") generatedSecrets
    dumpKeyfiles (dir, pat) gsDlgIssuersSecrets gsRichSecrets gsPoorSecrets
    dumpFakeAvvmSeeds dir gsFakeAvvmSeeds

dumpKeyfiles
    :: (MonadIO m, MonadThrow m, WithLogger m)
    => (FilePath, FilePath) -- directory and key-file pattern
    -> [SecretKey]
    -> [RichSecrets]
    -> [EncryptedSecretKey]
    -> m ()
dumpKeyfiles (dir, pat) dlgIssuers richs poors = do
    let keysDir = dir </> "generated-keys"
    let dlgIssuersDir = keysDir </> "dlg-issuers"
    let richDir = keysDir </> "rich"
    let poorDir = keysDir </> "poor"
    logInfo $ "Dumping generated genesis secrets into " <> fromString keysDir
    mapM_ (liftIO . createDirectoryIfMissing True)
        [ dlgIssuersDir
        , richDir
        , poorDir
        ]

    let totalSecrets = length dlgIssuers + length richs + length poors

    let patternize = applyPattern @Int pat
    forM_ (enumerate dlgIssuers) $ \(i, sk) ->
        dumpDlgIssuerSecret (dlgIssuersDir </> patternize i) sk
    forM_ (enumerate richs) $ \(i, richSecrets) ->
        dumpRichSecrets (richDir </> patternize i) richSecrets
    forM_ (enumerate poors) $ \(i, hdwSk) ->
        dumpPoorSecret (poorDir </> patternize i) hdwSk

    logInfo $ show totalSecrets <> " keyfiles are generated"

dumpFakeAvvmSeeds
    :: (MonadIO m, WithLogger m)
    => FilePath
    -> [ByteString]
    -> m ()
dumpFakeAvvmSeeds dir seeds = do
    let keysDir = dir </> "keys-fakeavvm"
    logInfo $ "Generating fake avvm data into " <> fromString keysDir
    liftIO $ createDirectoryIfMissing True keysDir
    let faoCount = length seeds

    forM_ (enumerate seeds) $ \(i :: Int, seed) ->
        dumpFakeAvvmSeed (keysDir </> ("fake-" <> show i <> ".seed")) seed

    logInfo (show faoCount <> " fake avvm seeds are generated")

----------------------------------------------------------------------------
-- Helpers
----------------------------------------------------------------------------

dumpUserSecret
    :: (MonadIO m, MonadThrow m, WithLogger m)
    => FilePath
    -> (UserSecret -> UserSecret)
    -> m ()
dumpUserSecret fp operation = do
    initializeUserSecret fp
    us <- takeUserSecret fp
    writeUserSecretRelease (operation us)

-- Replace "{}" with the result of applying 'show' to the given
-- value.
applyPattern :: Show a => FilePath -> a -> FilePath
applyPattern fp a = replace "{}" (show a) fp
  where
    replace :: FilePath -> FilePath -> FilePath -> FilePath
    replace x b = toString . (T.replace `on` toText) x b . toText
{'fraction_non_alphanumeric': 0.17854657520628292, 'fraction_numerical': 0.0018888557510686947, 'mean_word_length': 1.7705866152575047, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1747303', 'n_tokens_mistral': 2767, 'n_tokens_neox': 2718, 'n_words': 778}