@@ -8,8 +8,9 @@ module EVM.Fetch
88 , RpcInfo (.. )
99 , RpcQuery (.. )
1010 , EVM.Fetch. zero
11+ , noRpc
12+ , noRpcFetcher
1113 , BlockNumber (.. )
12- , mkRpcInfo
1314 , mkSession
1415 , mkSessionWithoutCache
1516 , Session (.. )
@@ -46,15 +47,14 @@ import Data.Bifunctor (first)
4647import Control.Exception (try , SomeException )
4748
4849import Control.Monad.Trans.Maybe
49- import Control.Applicative (Alternative (.. ))
5050import Data.Aeson hiding (Error )
5151import Data.Aeson.Optics
5252import Data.ByteString qualified as BS
5353import Data.Text (Text , unpack , pack )
5454import Data.Text qualified as T
5555import Data.Foldable (Foldable (.. ))
5656import Data.Map.Strict qualified as Map
57- import Data.Maybe (fromMaybe , isJust , fromJust )
57+ import Data.Maybe (fromMaybe , isJust , fromJust , isNothing )
5858import Data.Vector qualified as RegularVector
5959import Network.Wreq
6060import Network.Wreq.Session qualified as NetSession
@@ -137,18 +137,11 @@ instance ToJSON RPCContract
137137
138138instance FromJSON RPCContract
139139
140- data RpcInfo = RpcInfo
141- { blockNumURL :: Maybe (BlockNumber , Text ) -- ^ (block number, RPC url)
142- }
140+ newtype RpcInfo = RpcInfo { blockNumURL :: Maybe (BlockNumber , Text )} -- ^ (block number, RPC url)
143141 deriving (Show )
144- instance Semigroup RpcInfo where
145- RpcInfo a1 <> RpcInfo b1 =
146- RpcInfo (a1 <|> b1)
147- instance Monoid RpcInfo where
148- mempty = RpcInfo Nothing
149142
150- mkRpcInfo :: Maybe ( BlockNumber , Text ) -> RpcInfo
151- mkRpcInfo blockNumURL = RpcInfo blockNumURL
143+ noRpc :: RpcInfo
144+ noRpc = RpcInfo Nothing
152145
153146rpc :: String -> [Value ] -> Value
154147rpc method args = object
@@ -422,7 +415,10 @@ zero :: Natural -> Maybe Natural -> Fetcher t m
422415zero smtjobs smttimeout q = do
423416 sess <- mkSessionWithoutCache
424417 withSolvers Z3 smtjobs 1 smttimeout $ \ s ->
425- oracle s (Just sess) mempty q
418+ oracle s (Just sess) noRpc q
419+
420+ noRpcFetcher :: forall t m . App m => SolverGroup -> Fetcher t m
421+ noRpcFetcher sg = oracle sg Nothing noRpc
426422
427423-- SMT solving + RPC data fetching + reading from environment
428424oracle :: forall t m . App m => SolverGroup -> Maybe Session -> RpcInfo -> Fetcher t m
@@ -450,65 +446,60 @@ oracle solvers preSess rpcInfo q = do
450446 let pathconds = foldl' PAnd (PBool True ) pathconditions
451447 continue <$> getSolutions solvers symExpr numBytes pathconds
452448
453- PleaseFetchContract addr base continue -> withSession addr (continue (nothingContract base addr)) $ \ sess -> do
454- conf <- readConfig
455- cache <- liftIO $ readMVar sess. sharedCache
456- case Map. lookup addr cache. contractCache of
457- Just c -> do
458- when (conf. debug) $ liftIO $ putStrLn $ " -> Using cached contract at " ++ show addr
459- pure $ continue $ makeContractFromRPC c
460- Nothing -> do
461- when (conf. debug) $ liftIO $ putStrLn $ " Fetching contract at " ++ show addr
462- contract <- case rpcInfo. blockNumURL of
463- Nothing -> do
464- liftIO $ putStrLn $ " Warning: no RPC info provided, returning empty contract for address: " <> show addr
465- pure $ Just $ nothingContract base addr
466- Just (block, url) -> liftIO $ fmap (fmap makeContractFromRPC) $ fetchContractWithSession conf sess block url addr
467- case contract of
468- Just x -> pure $ continue x
469- Nothing -> internalError $ " oracle error: " ++ show q
470-
471- PleaseFetchSlot addr slot continue -> withSession addr (continue 0 )$ \ sess -> do
472- conf <- readConfig
473- cache <- liftIO $ readMVar sess. sharedCache
474- case Map. lookup (addr, slot) cache. slotCache of
475- Just s -> do
476- when (conf. debug) $ liftIO $ putStrLn $ " -> Using cached slot value for slot " <> show slot <> " at " <> show addr
477- pure $ continue s
478- Nothing -> do
479- when (conf. debug) $ liftIO $ putStrLn $ " Fetching slot " <> (show slot) <> " at " <> (show addr)
480- case rpcInfo. blockNumURL of
481- Nothing -> do
482- liftIO $ putStrLn $ " Warning: no RPC info provided, returning 0 for slot at address: " <> show addr
483- pure $ continue 0
484- Just (block, url) -> do
485- n <- liftIO $ getLatestBlockNum conf sess block url
486- ret <- liftIO $ fetchSlotWithSession sess. sess n url addr slot
487- when (isJust ret) $ let val = fromJust ret in
488- liftIO $ modifyMVar_ sess. sharedCache $ \ c ->
489- pure $ c { slotCache = Map. insert (addr, slot) val c. slotCache }
490- case ret of
491- Just x -> pure $ continue x
492- Nothing -> internalError $ " oracle error: " ++ show q
449+ PleaseFetchContract addr base continue
450+ | isAddressSpecial addr -> pure $ continue nothingContract
451+ | isNothing rpcInfo. blockNumURL -> pure $ continue nothingContract
452+ | otherwise -> do
453+ let sess = fromMaybe (internalError $ " oracle: no session provided for fetch addr: " ++ show addr) preSess
454+ conf <- readConfig
455+ cache <- liftIO $ readMVar sess. sharedCache
456+ case Map. lookup addr cache. contractCache of
457+ Just c -> do
458+ when (conf. debug) $ liftIO $ putStrLn $ " -> Using cached contract at " ++ show addr
459+ pure $ continue $ makeContractFromRPC c
460+ Nothing -> do
461+ when (conf. debug) $ liftIO $ putStrLn $ " Fetching contract at " ++ show addr
462+ let (block, url) = fromJust rpcInfo. blockNumURL
463+ contract <- liftIO $ fmap (fmap makeContractFromRPC) $ fetchContractWithSession conf sess block url addr
464+ case contract of
465+ Just x -> pure $ continue x
466+ Nothing -> internalError $ " oracle error: " ++ show q
467+ where
468+ nothingContract = case base of
469+ AbstractBase -> unknownContract (LitAddr addr)
470+ EmptyBase -> emptyContract
471+
472+ PleaseFetchSlot addr slot continue
473+ | isAddressSpecial addr -> pure $ continue 0
474+ | isNothing rpcInfo. blockNumURL -> pure $ continue 0
475+ | otherwise -> do
476+ let sess = fromMaybe (internalError $ " oracle: no session provided for fetch addr: " ++ show addr) preSess
477+ conf <- readConfig
478+ cache <- liftIO $ readMVar sess. sharedCache
479+ case Map. lookup (addr, slot) cache. slotCache of
480+ Just s -> do
481+ when (conf. debug) $ liftIO $ putStrLn $ " -> Using cached slot value for slot " <> show slot <> " at " <> show addr
482+ pure $ continue s
483+ Nothing -> do
484+ when (conf. debug) $ liftIO $ putStrLn $ " Fetching slot " <> (show slot) <> " at " <> (show addr)
485+ let (block, url) = fromJust rpcInfo. blockNumURL
486+ n <- liftIO $ getLatestBlockNum conf sess block url
487+ ret <- liftIO $ fetchSlotWithSession sess. sess n url addr slot
488+ when (isJust ret) $ let val = fromJust ret in
489+ liftIO $ modifyMVar_ sess. sharedCache $ \ c ->
490+ pure $ c { slotCache = Map. insert (addr, slot) val c. slotCache }
491+ case ret of
492+ Just x -> pure $ continue x
493+ Nothing -> internalError $ " oracle error: " ++ show q
493494
494495 PleaseReadEnv variable continue -> do
495496 value <- liftIO $ lookupEnv variable
496497 pure . continue $ fromMaybe " " value
497498
498499 where
499- nothingContract base addr =
500- case base of
501- AbstractBase -> unknownContract (LitAddr addr)
502- EmptyBase -> emptyContract
503- withSession addr def f =
504- case addr of
505- -- special values such as 0, 0xdeadbeef, 0xacab, hevm cheatcodes, and the precompile addresses
506- -- do not require a session, there is nothing deployed there, it's way too small or special, RPC would be pointless
507- a | a <= 0xdeadbeef -> pure def
508- 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D -> pure def
509- _ -> case preSess of
510- Just sess -> f sess
511- Nothing -> internalError $ " oracle: no session provided for fetch addr: " ++ show addr
500+ -- special values such as 0, 0xdeadbeef, 0xacab, hevm cheatcodes, and the precompile addresses
501+ isAddressSpecial addr = addr <= 0xdeadbeef || addr == 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D
502+
512503
513504getSolutions :: forall m . App m => SolverGroup -> Expr EWord -> Int -> Prop -> m (Maybe [W256 ])
514505getSolutions solvers symExprPreSimp numBytes pathconditions = do
0 commit comments