Skip to content

Commit b07c460

Browse files
committed
New queue idea
Cleanup More generic interpret Update Making progress Making progress Update Update Update Making progress Update Now typecheck Update Making progress Update Better now Making progress Update Typechecks now Update Better Some improvement? Better I think Update Update Making progress Update to fix changes Fixing Update Better Let's hope this works Cleaner Update Update Less noise Update Much better Update Fixing Update Update Update QED change Qed fixing still Fixed Qed Update to fix cli Ooops, fixing bug Better printing Cleanup Cleanup Cleanup Cleanup Trying to rebase on top of main Add changelog Less braces Less change
1 parent acb72d0 commit b07c460

File tree

13 files changed

+433
-428
lines changed

13 files changed

+433
-428
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Replaced RPC mocking by a full block cache support. This allows users to cache responses from an RPC
1515
node via `--cache-dir dir`.
1616
- Changed `verify*` methods to always require postcodition.
17+
- We now use a symbolic execution queue, so as not to run out of resources when there are
18+
too many branches to explore.
1719

1820
## [0.56.0] - 2025-10-13
1921

cli/cli.hs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import EVM.Concrete qualified as Concrete
4646
import GitHash
4747
import EVM.FeeSchedule (feeSchedule)
4848
import EVM.Fetch qualified as Fetch
49-
import EVM.Format (hexByteString, strip0x, formatExpr)
49+
import EVM.Format (hexByteString, strip0x, formatExpr, indent)
5050
import EVM.Solidity
5151
import EVM.Solvers
5252
import EVM.Stepper qualified
@@ -527,7 +527,7 @@ symbCheck cFileOpts sOpts cExecOpts cOpts = do
527527
cache <- readMVar sess.sharedCache
528528
Fetch.saveCache dir block cache
529529
case res of
530-
[Qed] -> do
530+
[] -> do
531531
liftIO $ putStrLn "\nQED: No reachable property violations discovered\n"
532532
showExtras solvers sOpts calldata expr
533533
_ -> do
@@ -540,26 +540,29 @@ symbCheck cFileOpts sOpts cExecOpts cOpts = do
540540
, ""
541541
] <> fmap (formatCex (fst calldata) Nothing) cexs
542542
liftIO $ T.putStrLn $ T.unlines counterexamples
543-
liftIO $ printWarnings Nothing [expr] res "symbolically"
543+
liftIO $ printWarnings Nothing expr res "symbolically"
544544
showExtras solvers sOpts calldata expr
545545
liftIO exitFailure
546546

547-
showExtras :: App m => SolverGroup ->SymbolicOptions -> (Expr Buf, [Prop]) -> Expr End -> m ()
547+
showExtras :: App m => SolverGroup ->SymbolicOptions -> (Expr Buf, [Prop]) -> [Expr End] -> m ()
548548
showExtras solvers sOpts calldata expr = do
549549
when sOpts.showTree $ liftIO $ do
550-
putStrLn "=== Expression ===\n"
551-
T.putStrLn $ formatExpr $ Expr.simplify expr
550+
putStrLn "=== Leafs ===\n"
551+
printLeafs $ map (formatExpr . Expr.simplify) expr
552552
putStrLn ""
553553
when sOpts.showReachableTree $ do
554554
reached <- reachable solvers expr
555555
liftIO $ do
556-
putStrLn "=== Potentially Reachable Expression ===\n"
557-
T.putStrLn (formatExpr . Expr.simplify $ reached)
556+
putStrLn "=== Potentially Reachable Leafs ===\n"
557+
printLeafs $ map (formatExpr . Expr.simplify) reached
558558
putStrLn ""
559559
when sOpts.getModels $ do
560-
liftIO $ putStrLn $ "=== Models for " <> show (Expr.numBranches expr) <> " branches ==="
560+
liftIO $ putStrLn $ "=== Models for " <> show (length expr) <> " branches ==="
561561
ms <- produceModels solvers expr
562562
liftIO $ forM_ ms (showModel (fst calldata))
563+
where
564+
printLeafs leafs =
565+
T.putStrLn $ indent 2 $ T.unlines $ zipWith (\i r -> "Leaf " <> T.pack (show (i :: Integer)) <> ":\n" <> r) [0..] leafs
563566

564567
isTestOrLib :: Text -> Bool
565568
isTestOrLib file = T.isSuffixOf ".t.sol" file || areAnyPrefixOf ["src/test/", "src/tests/", "lib/"] file

src/EVM.hs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,14 +2669,12 @@ traceForest' :: Expr End -> Forest Trace
26692669
traceForest' (Success _ (TraceContext f _ _) _ _) = f
26702670
traceForest' (Partial _ (TraceContext f _ _) _) = f
26712671
traceForest' (Failure _ (TraceContext f _ _) _) = f
2672-
traceForest' (ITE {}) = internalError"Internal Error: ITE does not contain a trace"
26732672
traceForest' (GVar {}) = internalError"Internal Error: Unexpected GVar"
26742673

26752674
traceContext :: Expr End -> TraceContext
26762675
traceContext (Success _ c _ _) = c
26772676
traceContext (Partial _ c _) = c
26782677
traceContext (Failure _ c _) = c
2679-
traceContext (ITE {}) = internalError"Internal Error: ITE does not contain a trace"
26802678
traceContext (GVar {}) = internalError"Internal Error: Unexpected GVar"
26812679

26822680
traceTopLog :: [Expr Log] -> EVM t s ()
@@ -3092,7 +3090,7 @@ instance VMOps Symbolic where
30923090
assign (#iterations % at loc) (Just (iteration + 1, stack))
30933091
continue v
30943092
-- Both paths are possible; we ask for more input
3095-
runBothPaths loc exploreDepth UnknownBranch =
3093+
runBothPaths loc exploreDepth UnknownBranch = do
30963094
(runBoth depthLimit exploreDepth ) . PleaseRunBoth condSimp $ (runBothPaths loc exploreDepth) . Case
30973095

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

src/EVM/Expr.hs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,11 +1076,6 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
10761076
| a == b = Lit 1
10771077
| otherwise = eq a b
10781078

1079-
-- redundant ITE
1080-
go (ITE (Lit x) a b)
1081-
| x == 0 = b
1082-
| otherwise = a
1083-
10841079
-- Masking as as per Solidity bit-packing of e.g. function parameters
10851080
go (And (Lit mask1) (Or (And (Lit mask2) _) x)) | (mask1 .&. mask2 == 0)
10861081
= And (Lit mask1) x
@@ -1228,13 +1223,6 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
12281223
| b == (Lit 0) = a
12291224
| otherwise = EVM.Expr.or a b
12301225

1231-
-- If x is ever non zero the Or will always evaluate to some non zero value and the false branch will be unreachable
1232-
-- NOTE: with AND this does not work, because and(0x8, 0x4) = 0
1233-
go (ITE (Or (Lit x) a) t f)
1234-
| x == 0 = ITE a t f
1235-
| otherwise = t
1236-
go (ITE (Or a b@(Lit _)) t f) = ITE (Or b a) t f
1237-
12381226
-- we write at least 32, so if x <= 32, it's FALSE
12391227
go o@(EVM.Types.LT (BufLength (WriteWord {})) (Lit x))
12401228
| x <= 32 = Lit 0
@@ -1672,10 +1660,6 @@ max (Lit 0) y = y
16721660
max x (Lit 0) = x
16731661
max x y = normArgs Max Prelude.max x y
16741662

1675-
numBranches :: Expr End -> Int
1676-
numBranches (ITE _ t f) = numBranches t + numBranches f
1677-
numBranches _ = 1
1678-
16791663
allLit :: [Expr Byte] -> Bool
16801664
allLit = all isLitByte
16811665

src/EVM/Format.hs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module EVM.Format
1616
, showTraceTree'
1717
, showValues
1818
, prettyvmresult
19+
, prettyvmresults
1920
, showCall
2021
, showWordExact
2122
, showWordExplanation
@@ -201,7 +202,6 @@ showTraceTree dapp vm =
201202
in pack $ concatMap showTree traces
202203

203204
showTraceTree' :: DappInfo -> Expr End -> Text
204-
showTraceTree' _ (ITE {}) = internalError "ITE does not contain a trace"
205205
showTraceTree' dapp leaf =
206206
let ?context = DappContext { info = dapp, contracts, labels }
207207
in let forest = traceForest' leaf
@@ -453,6 +453,10 @@ prettyvmresult (Failure _ _ err) = prettyError err
453453
prettyvmresult (Partial _ _ p) = T.unpack $ formatPartial p
454454
prettyvmresult r = internalError $ "Invalid result: " <> show r
455455

456+
prettyvmresults :: [Expr End] -> String
457+
prettyvmresults results =
458+
T.unpack $ indent 2 $ T.unlines $ zipWith (\i r -> T.pack ("Result " <> show (i :: Integer) <> ": " <> prettyvmresult r)) [0..] results
459+
456460
indent :: Int -> Text -> Text
457461
indent n = rstrip . T.unlines . fmap (T.replicate n (T.pack [' ']) <>) . T.lines
458462

@@ -565,14 +569,6 @@ formatExpr = go
565569
(GVar v) -> "(GVar " <> T.pack (show v) <> ")"
566570
LitByte w -> T.pack $ show w
567571

568-
ITE c t f -> T.unlines
569-
[ "(ITE"
570-
, indent 2 $ T.unlines
571-
[ formatExpr c
572-
, formatExpr t
573-
, formatExpr f
574-
]
575-
, ")"]
576572
Success asserts _ buf store -> T.unlines
577573
[ "(Success"
578574
, indent 2 $ T.unlines

src/EVM/Stepper.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ runFully = do
9898
enter :: Text -> Stepper t s ()
9999
enter t = evm (EVM.pushTrace (EntryTrace t))
100100

101+
-- Concrete interpretation
101102
interpret
102103
:: forall m a . (App m)
103104
=> Fetch.Fetcher Concrete m RealWorld

0 commit comments

Comments
 (0)