@@ -18,6 +18,7 @@ import System.Random (mkStdGen)
1818import Data.IORef (IORef , writeIORef , readIORef , atomicModifyIORef' )
1919import Data.Map (Map )
2020import qualified Data.Map as Map
21+ import qualified Data.Set as Set
2122import System.Directory (getCurrentDirectory )
2223
2324import Echidna.Output.Source (saveLcovHook )
@@ -198,10 +199,10 @@ fuzzerLoop callback vm testLimit bus = do
198199 void $ saveLcovHook env dir env. sourceCache contracts
199200 putStrLn $ " Fuzzer " ++ show workerId ++ " : dumped LCOV coverage."
200201 pure ()
201- Just (WrappedMessage _ (ToFuzzer tid (FuzzSequence txs))) -> do
202+ Just (WrappedMessage _ (ToFuzzer tid (FuzzSequence txs prob ))) -> do
202203 workerId <- gets (. workerId)
203204 when (tid == workerId) $ do
204- modify' $ \ s -> s { prioritizedSequences = txs : s. prioritizedSequences }
205+ modify' $ \ s -> s { prioritizedSequences = (prob, txs) : s. prioritizedSequences }
205206 pure ()
206207 Just (WrappedMessage _ (ToFuzzer tid ClearPrioritization )) -> do
207208 workerId <- gets (. workerId)
@@ -233,11 +234,16 @@ randseq deployedContracts = do
233234 seqLen = env. cfg. campaignConf. seqLen
234235
235236 prioritized <- gets (. prioritizedSequences)
236- usePrioritized <- (<= (0.90 :: Double )) <$> getRandom
237237
238- if not (null prioritized) && usePrioritized
239- then do
240- seqPrototype <- rElem (NE. fromList prioritized)
238+ mbSeq <- if null prioritized
239+ then pure Nothing
240+ else do
241+ (prob, seqPrototype) <- rElem (NE. fromList prioritized)
242+ useIt <- (<= prob) <$> getRandom
243+ pure $ if useIt then Just seqPrototype else Nothing
244+
245+ case mbSeq of
246+ Just seqPrototype -> do
241247 let expandPrototype [] = return []
242248 expandPrototype [p] = do
243249 tx <- genTxFromPrototype world deployedContracts p
@@ -250,14 +256,29 @@ randseq deployedContracts = do
250256 return ((tx : rndTxs) ++ rest)
251257
252258 expandedTxs <- expandPrototype seqPrototype
253- let len = length expandedTxs
259+ corpusSet <- liftIO $ readIORef env. corpusRef
260+ prefix <- if Set. null corpusSet
261+ then pure []
262+ else do
263+ idx <- getRandomR (0 , Set. size corpusSet - 1 )
264+ let (_, cTxs) = Set. elemAt idx corpusSet
265+ let middleLen = length expandedTxs
266+ let maxPrefix = seqLen - middleLen
267+ if maxPrefix <= 0
268+ then pure []
269+ else do
270+ k <- getRandomR (0 , min (length cTxs) maxPrefix)
271+ pure (take k cTxs)
272+
273+ let combined = prefix ++ expandedTxs
274+ let len = length combined
254275 if len < seqLen
255276 then do
256277 paddingTxs <- replicateM (seqLen - len) (genTx world deployedContracts)
257- pure (expandedTxs ++ paddingTxs)
278+ pure (combined ++ paddingTxs)
258279 else
259- pure (take seqLen expandedTxs )
260- else do
280+ pure (take seqLen combined )
281+ Nothing -> do
261282 -- Generate new random transactions
262283 randTxs <- replicateM seqLen (genTx world deployedContracts)
263284 -- Generate a random mutator
0 commit comments