{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module: Worker.Simulation -- Copyright: Copyright © 2020 Kadena LLC. -- License: MIT -- Maintainer: Lars Kuhtz -- Stability: experimental -- -- Simulation Mining Worker -- -- A fake mining worker that is not actually doing any work. It calculates the -- solve time base on the assumed hash power of the worker thread and returns -- the work bytes unchanged after that time has passed. -- module Worker.Simulation ( HashRate(..) , defaultHashRate , simulationWorker ) where import Control.Concurrent (threadDelay) import Data.Aeson import Data.Hashable import qualified Data.Text as T import GHC.Generics import System.LogLevel import qualified System.Random.MWC as MWC import qualified System.Random.MWC.Distributions as MWC -- internal modules import Logger import Worker -- -------------------------------------------------------------------------- -- -- HashRate newtype HashRate = HashRate Double deriving (Show, Eq, Ord, Generic) deriving newtype (Read, Num, Fractional, Floating, Real, Enum, Hashable, ToJSON, FromJSON) -- | Default is 1MH defaultHashRate :: HashRate defaultHashRate = 1_000_000 -- -------------------------------------------------------------------------- -- -- Simulation Mining Worker -- | A fake mining worker that is not actually doing any work. It calculates the -- solve time base on the assumed hash power of the worker thread and returns -- the work bytes unchanged after that time has passed. -- simulationWorker :: Logger -> MWC.GenIO -> HashRate -> Worker simulationWorker logger rng rate _nonce (Target targetNat) work = do delay <- round <$> MWC.exponential scale rng logg Info $ "solve time (microseconds): " <> T.pack (show delay) threadDelay delay return work where logg = writeLog logger -- expectedMicros = 1_000_000 * difficulty / rate -- MWC.exponential is parameterized by the rate, i.e. 1 / expected_time scale = realToFrac $ realToFrac rate / (difficulty * 1_000_000) -- the expected number of attempts for solving a target is the difficulty. difficulty :: Rational difficulty = 2^(256 :: Integer) / targetNum -- Target is an little endian encoded (unsigned) 256 bit word. targetNum :: Rational targetNum = fromIntegral targetNat