@@ -40,6 +40,12 @@ import EVM.Types
4040maxLit :: W256
4141maxLit = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
4242
43+ maxLitSigned :: W256
44+ maxLitSigned = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
45+
46+ minLitSigned :: W256
47+ minLitSigned = 0x1000000000000000000000000000000000000000000000000000000000000000
48+
4349-- ** Stack Ops ** ---------------------------------------------------------------------------------
4450
4551
@@ -103,14 +109,12 @@ smod = op2 SMod (\x y ->
103109
104110addmod :: Expr EWord -> Expr EWord -> Expr EWord -> Expr EWord
105111addmod = op3 AddMod (\ x y z ->
106- if z == 0
107- then 0
112+ if z == 0 then 0
108113 else fromIntegral $ (into @ Word512 x + into y) `Prelude.mod` into z)
109114
110115mulmod :: Expr EWord -> Expr EWord -> Expr EWord -> Expr EWord
111116mulmod = op3 MulMod (\ x y z ->
112- if z == 0
113- then 0
117+ if z == 0 then 0
114118 else fromIntegral $ (into @ Word512 x * into y) `Prelude.mod` into z)
115119
116120exp :: Expr EWord -> Expr EWord -> Expr EWord
@@ -203,13 +207,20 @@ sar = op2 SAR (\x y ->
203207
204208peq :: (Typeable a ) => Expr a -> Expr a -> Prop
205209peq (Lit x) (Lit y) = PBool (x == y)
210+ peq (LitAddr x) (LitAddr y) = PBool (x == y)
206211peq (LitByte x) (LitByte y) = PBool (x == y)
207212peq (ConcreteBuf x) (ConcreteBuf y) = PBool (x == y)
208213peq a b
209214 | a == b = PBool True
210215 | otherwise = let args = sort [a, b]
211216 in PEq (args !! 0 ) (args !! 1 )
212217
218+ pleq :: Expr EWord -> Expr EWord -> Prop
219+ pleq (Lit a) (Lit b) = PBool (a <= b)
220+ pleq a b
221+ | a == b = PBool True
222+ | otherwise = PLEq a b
223+
213224-- ** Bufs ** --------------------------------------------------------------------------------------
214225
215226
@@ -1057,21 +1068,9 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
10571068
10581069 go (IndexWord a b) = indexWord a b
10591070
1060- -- LT
1061- go (EVM.Types. LT (Lit a) (Lit b))
1062- | a < b = Lit 1
1063- | otherwise = Lit 0
1064- go (EVM.Types. LT _ (Lit 0 )) = Lit 0
1065- go (EVM.Types. LT a (Lit 1 )) = iszero a
1066- go (EVM.Types. LT (Lit 0 ) a) = iszero (Eq (Lit 0 ) a)
10671071
1068- -- normalize all comparisons in terms of LT
1069- go (EVM.Types. GT a b) = lt b a
1070- go (EVM.Types. GEq a b) = leq b a
1071- go (EVM.Types. LEq a b) = iszero (lt b a)
1072- go (SLT a@ (Lit _) b@ (Lit _)) = slt a b
1073- go (SGT a b) = SLT b a
10741072 go (SEx a (SEx a2 b)) | a == a2 = sex a b
1073+ go (SEx _ (Lit 0 )) = Lit 0
10751074 go (SEx a b) = sex a b
10761075
10771076 -- IsZero
@@ -1106,14 +1105,6 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
11061105 -- literal addresses
11071106 go (WAddr (LitAddr a)) = Lit $ into a
11081107
1109- -- simple div/mod/add/sub
1110- go (Div o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. div o1 o2
1111- go (SDiv o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. sdiv o1 o2
1112- go (Mod o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. mod o1 o2
1113- go (SMod o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. smod o1 o2
1114- go (Add o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. add o1 o2
1115- go (Sub o1@ (Lit _) o2@ (Lit _)) = EVM.Expr. sub o1 o2
1116-
11171108 -- Mod
11181109 go (Mod _ (Lit 0 )) = Lit 0
11191110 go (SMod _ (Lit 0 )) = Lit 0
@@ -1122,6 +1113,18 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
11221113 go (Mod (Lit 0 ) _) = Lit 0
11231114 go (SMod (Lit 0 ) _) = Lit 0
11241115
1116+ -- MulMod
1117+ go (MulMod (Lit 0 ) _ _) = Lit 0
1118+ go (MulMod _ (Lit 0 ) _) = Lit 0
1119+ go (MulMod _ _ (Lit 0 )) = Lit 0
1120+ go (MulMod a b c) = mulmod a b c
1121+
1122+ -- AddMod
1123+ go (AddMod (Lit 0 ) a b) = Mod a b
1124+ go (AddMod a (Lit 0 ) b) = Mod a b
1125+ go (AddMod _ _ (Lit 0 )) = Lit 0
1126+ go (AddMod a b c) = addmod a b c
1127+
11251128 -- Triple And (must be before 3-way sort below)
11261129 go (And (Lit a) (And (Lit b) c)) = And (EVM.Expr. and (Lit a) (Lit b)) c
11271130
@@ -1207,9 +1210,11 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
12071210 -- SHL / SHR by 0
12081211 go (SHL a v)
12091212 | a == (Lit 0 ) = v
1213+ | v == (Lit 0 ) = v
12101214 | otherwise = shl a v
12111215 go (SHR a v)
12121216 | a == (Lit 0 ) = v
1217+ | v == (Lit 0 ) = v
12131218 | otherwise = shr a v
12141219
12151220 -- Bitwise AND & OR. These MUST preserve bitwise equivalence
@@ -1286,6 +1291,29 @@ simplifyNoLitToKeccak e = untilFixpoint (mapExpr go) e
12861291 then Lit 0
12871292 else o
12881293
1294+ -- normalize all comparisons in terms of (S)LT
1295+ go (EVM.Types. GT a b) = lt b a
1296+ go (EVM.Types. GEq a b) = leq b a
1297+ go (EVM.Types. LEq a b) = iszero (lt b a)
1298+ go (SGT a b) = slt b a
1299+
1300+ -- LT
1301+ go (EVM.Types. LT _ (Lit 0 )) = Lit 0
1302+ go (EVM.Types. LT a (Lit 1 )) = iszero a
1303+ go (EVM.Types. LT (Lit 0 ) a) = iszero (Eq (Lit 0 ) a)
1304+ go (EVM.Types. LT a b) = lt a b
1305+
1306+ -- SLT
1307+ go (SLT _ (Lit a)) | a == minLitSigned = Lit 0
1308+ go (SLT (Lit a) _) | a == maxLitSigned = Lit 0
1309+ go (SLT a b) = slt a b
1310+
1311+ -- simple div/mod/add/sub
1312+ go (Div o1 o2) = EVM.Expr. div o1 o2
1313+ go (SDiv o1 o2) = EVM.Expr. sdiv o1 o2
1314+ go (Mod o1 o2) = EVM.Expr. mod o1 o2
1315+ go (SMod o1 o2) = EVM.Expr. smod o1 o2
1316+
12891317 go a = a
12901318
12911319
@@ -1330,6 +1358,7 @@ simplifyProp prop =
13301358 go (PLEq (Sub a b) c) | a == c = PLEq b a
13311359 go (PLT (Max (Lit a) b) (Lit c)) | a < c = PLT b (Lit c)
13321360 go (PLT (Lit 0 ) (Eq a b)) = peq a b
1361+ go (PLEq a b) = pleq a b
13331362
13341363 -- when it's PLT but comparison on the RHS then it's just (PEq 1 RHS)
13351364 go (PLT (Lit 0 ) (a@ LT {})) = peq (Lit 1 ) a
@@ -1338,6 +1367,7 @@ simplifyProp prop =
13381367 go (PLT (Lit 0 ) (a@ GT {})) = peq (Lit 1 ) a
13391368 go (PLT (Lit 0 ) (a@ GEq {})) = peq (Lit 1 ) a
13401369 go (PLT (Lit 0 ) (a@ SGT {})) = peq (Lit 1 ) a
1370+ go (POr (PLEq a1 (Lit b)) (PLEq (Lit c) a2)) | a1 == a2 && c == b+ 1 = PBool True
13411371
13421372 -- negations
13431373 go (PNeg (PBool b)) = PBool (Prelude. not b)
@@ -1348,6 +1378,7 @@ simplifyProp prop =
13481378 go (PNeg (PLEq a b)) = PGT a b
13491379 go (PNeg (PAnd a b)) = POr (PNeg a) (PNeg b)
13501380 go (PNeg (POr a b)) = PAnd (PNeg a) (PNeg b)
1381+ go (PNeg (PEq (Lit 1 ) (IsZero b))) = PEq (Lit 0 ) (IsZero b)
13511382
13521383 -- Empty buf
13531384 go (PEq (Lit 0 ) (BufLength k)) = peq k (ConcreteBuf " " )
@@ -1739,6 +1770,10 @@ concKeccakSimpExpr orig = untilFixpoint (simplifyNoLitToKeccak . (mapExpr concKe
17391770concKeccakProps :: [Prop ] -> [Prop ]
17401771concKeccakProps orig = untilFixpoint (map (mapProp concKeccakOnePass)) orig
17411772
1773+ -- As above, but also simplify, to fixedpoint
1774+ concKeccakSimpProps :: [Prop ] -> [Prop ]
1775+ concKeccakSimpProps orig = untilFixpoint (simplifyProps . map (mapProp concKeccakOnePass)) orig
1776+
17421777-- Simplifies in case the input to the Keccak is of specific array/map format and
17431778-- can be simplified into a concrete value
17441779-- Turns (Keccak ConcreteBuf) into a Lit
0 commit comments