Skip to content

Commit 0eb1fb0

Browse files
authored
Merge pull request #700 from ethereum/martin-unify-two-types
Unifying result type
2 parents 7e73f1d + 6c978d1 commit 0eb1fb0

File tree

11 files changed

+267
-259
lines changed

11 files changed

+267
-259
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8888
- block.number can now be symbolic. This only affects library use of hevm
8989
- Removed `--smtoutput` since it was never used
9090
- We now build with -DCMAKE_POLICY_VERSION_MINIMUM=3.5 libff, as cmake deprecated 3.5
91+
- CheckSatResult has now been unified with ProofResult via SMTResult
9192

9293
## [0.54.2] - 2024-12-12
9394

cli/cli.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,12 +495,12 @@ assert cFileOpts sOpts cExecOpts cOpts = do
495495
}
496496
(expr, res) <- verify solvers veriOpts preState (Just $ checkAssertions errCodes)
497497
case res of
498-
[Qed _] -> do
498+
[Qed] -> do
499499
liftIO $ putStrLn "\nQED: No reachable property violations discovered\n"
500500
showExtras solvers sOpts calldata expr
501501
_ -> do
502502
let cexs = snd <$> mapMaybe getCex res
503-
smtUnknowns = mapMaybe getUnknown res
503+
smtUnknowns = snd <$> mapMaybe getUnknown res
504504
counterexamples
505505
| null cexs = []
506506
| otherwise =
@@ -528,7 +528,7 @@ showExtras solvers sOpts calldata expr = do
528528
when sOpts.showReachableTree $ do
529529
reached <- reachable solvers expr
530530
liftIO $ do
531-
putStrLn "=== Reachable Expression ===\n"
531+
putStrLn "=== Potentially Reachable Expression ===\n"
532532
T.putStrLn (formatExpr . snd $ reached)
533533
putStrLn ""
534534
when sOpts.getModels $ do

src/EVM.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3009,7 +3009,7 @@ instance VMOps Symbolic where
30093009
assign (#iterations % at loc) (Just (iteration + 1, stack))
30103010
continue v
30113011
-- Both paths are possible; we ask for more input
3012-
runBothPaths loc exploreDepth Unknown =
3012+
runBothPaths loc exploreDepth UnknownBranch =
30133013
(runBoth depthLimit exploreDepth ) . PleaseRunBoth condSimp $ (runBothPaths loc exploreDepth) . Case
30143014

30153015
-- numBytes allows us to specify how many bytes of the returned value is relevant

src/EVM/Fetch.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,17 @@ checkBranch solvers branchcondition pathconditions = do
275275
let props = [pathconditions .&& branchcondition]
276276
checkSatWithProps solvers props >>= \case
277277
-- the condition is unsatisfiable
278-
(Unsat, _) -> -- if pathconditions are consistent then the condition must be false
278+
(Qed, _) -> -- if pathconditions are consistent then the condition must be false
279279
pure $ Case False
280280
-- Sat means its possible for condition to hold
281-
(Sat {}, _) -> do -- is its negation also possible?
281+
(Cex {}, _) -> do -- is its negation also possible?
282282
let propsNeg = [pathconditions .&& (PNeg branchcondition)]
283283
checkSatWithProps solvers propsNeg >>= \case
284284
-- No. The condition must hold
285-
(Unsat, _) -> pure $ Case True
285+
(Qed, _) -> pure $ Case True
286286
-- Yes. Both branches possible
287-
(Sat {}, _) -> pure EVM.Types.Unknown
287+
(Cex {}, _) -> pure UnknownBranch
288288
-- If the query times out, or can't be executed (e.g. symbolic copyslice) we simply explore both paths
289-
_ -> pure EVM.Types.Unknown
289+
_ -> pure UnknownBranch
290290
-- If the query times out, or can't be executed (e.g. symbolic copyslice) we simply explore both paths
291-
_ -> pure EVM.Types.Unknown
291+
_ -> pure UnknownBranch

src/EVM/Fuzz.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Data.Word (Word8)
1515

1616
import EVM.Expr qualified as Expr
1717
import EVM.Expr (bytesToW256)
18-
import EVM.SMT qualified as SMT (BufModel(..), SMTCex(..))
18+
import EVM.Types qualified as SMT
1919
import EVM.Traversals
2020
import EVM.Types (Prop(..), W256, Expr(..), EType(..), internalError, keccak')
2121

src/EVM/SMT.hs

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -77,56 +77,6 @@ instance Monoid CexVars where
7777
, txContext = mempty
7878
}
7979

80-
-- | A model for a buffer, either in it's compressed form (for storing parsed
81-
-- models from a solver), or as a bytestring (for presentation to users)
82-
data BufModel
83-
= Comp CompressedBuf
84-
| Flat ByteString
85-
deriving (Eq)
86-
instance Show BufModel where
87-
show (Comp c) = "Comp " <> show c
88-
show (Flat b) = "Flat 0x" <> bsToHex b
89-
90-
-- | This representation lets us store buffers of arbitrary length without
91-
-- exhausting the available memory, it closely matches the format used by
92-
-- smt-lib when returning models for arrays
93-
data CompressedBuf
94-
= Base { byte :: Word8, length :: W256}
95-
| Write { byte :: Word8, idx :: W256, next :: CompressedBuf }
96-
deriving (Eq, Show)
97-
98-
99-
-- | a final post shrinking cex, buffers here are all represented as concrete bytestrings
100-
data SMTCex = SMTCex
101-
{ vars :: Map (Expr EWord) W256
102-
, addrs :: Map (Expr EAddr) Addr
103-
, buffers :: Map (Expr Buf) BufModel
104-
, store :: Map (Expr EAddr) (Map W256 W256)
105-
, blockContext :: Map (Expr EWord) W256
106-
, txContext :: Map (Expr EWord) W256
107-
}
108-
deriving (Eq, Show)
109-
110-
instance Semigroup SMTCex where
111-
a <> b = SMTCex
112-
{ vars = a.vars <> b.vars
113-
, addrs = a.addrs <> b.addrs
114-
, buffers = a.buffers <> b.buffers
115-
, store = a.store <> b.store
116-
, blockContext = a.blockContext <> b.blockContext
117-
, txContext = a.txContext <> b.txContext
118-
}
119-
120-
instance Monoid SMTCex where
121-
mempty = SMTCex
122-
{ vars = mempty
123-
, addrs = mempty
124-
, buffers = mempty
125-
, store = mempty
126-
, blockContext = mempty
127-
, txContext = mempty
128-
}
129-
13080
flattenBufs :: SMTCex -> Maybe SMTCex
13181
flattenBufs cex = do
13282
bs <- mapM collapse cex.buffers

src/EVM/Solvers.hs

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,9 @@ data MultiData = MultiData
7777

7878
data SingleData = SingleData
7979
{ smt2 :: SMT2
80-
, resultChan :: Chan CheckSatResult
80+
, resultChan :: Chan SMTResult
8181
}
8282

83-
-- | The result of a call to (check-sat)
84-
data CheckSatResult
85-
= Sat SMTCex
86-
| Unsat
87-
| Unknown String
88-
| Error String
89-
deriving (Show, Eq)
90-
91-
isSat :: CheckSatResult -> Bool
92-
isSat (Sat _) = True
93-
isSat _ = False
94-
95-
isUnsat :: CheckSatResult -> Bool
96-
isUnsat Unsat = True
97-
isUnsat _ = False
98-
9983
checkMulti :: SolverGroup -> Err SMT2 -> MultiSol -> IO (Maybe [W256])
10084
checkMulti (SolverGroup taskQueue) smt2 multiSol = do
10185
if isLeft smt2 then pure Nothing
@@ -107,20 +91,20 @@ checkMulti (SolverGroup taskQueue) smt2 multiSol = do
10791
-- collect result
10892
readChan resChan
10993

110-
checkSatWithProps :: App m => SolverGroup -> [Prop] -> m (CheckSatResult, Err SMT2)
94+
checkSatWithProps :: App m => SolverGroup -> [Prop] -> m (SMTResult, Err SMT2)
11195
checkSatWithProps (SolverGroup taskQueue) props = do
11296
conf <- readConfig
11397
let psSimp = simplifyProps props
114-
if psSimp == [PBool False] then pure (Unsat, Right mempty)
98+
if psSimp == [PBool False] then pure (Qed, Right mempty)
11599
else do
116100
let smt2 = assertProps conf psSimp
117101
if isLeft smt2 then
118-
let err = getError smt2 in pure (EVM.Solvers.Unknown err, Left err)
102+
let err = getError smt2 in pure (Error err, Left err)
119103
else do
120104
res <- liftIO $ checkSat (SolverGroup taskQueue) smt2
121105
pure (res, Right (getNonError smt2))
122106

123-
checkSat :: SolverGroup -> Err SMT2 -> IO CheckSatResult
107+
checkSat :: SolverGroup -> Err SMT2 -> IO SMTResult
124108
checkSat (SolverGroup taskQueue) smt2 = do
125109
if isLeft smt2 then pure $ Error $ getError smt2
126110
else do
@@ -227,7 +211,7 @@ getMultiSol smt2@(SMT2 cmds cexvars _) multiSol r inst availableInstances fileCo
227211
when conf.debug $ putStrLn $ "Unable to write SMT to solver: " <> (T.unpack err)
228212
writeChan r Nothing
229213

230-
getOneSol :: (MonadIO m, ReadConfig m) => SMT2 -> (Chan CheckSatResult) -> SolverInstance -> Chan SolverInstance -> Int -> m ()
214+
getOneSol :: (MonadIO m, ReadConfig m) => SMT2 -> (Chan SMTResult) -> SolverInstance -> Chan SolverInstance -> Int -> m ()
231215
getOneSol smt2@(SMT2 cmds cexvars ps) r inst availableInstances fileCounter = do
232216
conf <- readConfig
233217
let fuzzResult = tryCexFuzz ps conf.numCexFuzz
@@ -236,7 +220,7 @@ getOneSol smt2@(SMT2 cmds cexvars ps) r inst availableInstances fileCounter = do
236220
if (isJust fuzzResult)
237221
then do
238222
when (conf.debug) $ putStrLn $ " Cex found via fuzzing:" <> (show fuzzResult)
239-
writeChan r (Sat $ fromJust fuzzResult)
223+
writeChan r (Cex $ fromJust fuzzResult)
240224
else if Prelude.not conf.onlyCexFuzz then do
241225
-- reset solver and send all lines of provided script
242226
out <- sendScript inst ("(reset)" : cmds)
@@ -248,10 +232,10 @@ getOneSol smt2@(SMT2 cmds cexvars ps) r inst availableInstances fileCounter = do
248232
sat <- sendLine inst "(check-sat)"
249233
res <- do
250234
case sat of
251-
"unsat" -> pure Unsat
252-
"timeout" -> pure $ EVM.Solvers.Unknown "Result timeout by SMT solver"
253-
"unknown" -> pure $ EVM.Solvers.Unknown "Result unknown by SMT solver"
254-
"sat" -> Sat <$> getModel inst cexvars
235+
"unsat" -> pure Qed
236+
"timeout" -> pure $ Unknown "Result timeout by SMT solver"
237+
"unknown" -> pure $ Unknown "Result unknown by SMT solver"
238+
"sat" -> Cex <$> getModel inst cexvars
255239
_ -> pure . Error $ "Unable to parse SMT solver output: " <> T.unpack sat
256240
writeChan r res
257241
else do

0 commit comments

Comments
 (0)