{-# Language ForeignFunctionInterface #-}
module EVM.Precompiled (execute) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Foreign.C
import Foreign.Ptr
import Foreign.ForeignPtr
import System.IO.Unsafe
data EthjetContext
foreign import ccall "ethjet_init"
ethjet_init :: IO (Ptr EthjetContext)
foreign import ccall "ðjet_free"
ethjet_free :: FunPtr (Ptr EthjetContext -> IO ())
foreign import ccall "ethjet"
ethjet
:: Ptr EthjetContext
-> CInt
-> Ptr CChar -> CInt
-> Ptr CChar -> CInt
-> IO CInt
globalContext :: ForeignPtr EthjetContext
{-# NOINLINE globalContext #-}
globalContext =
unsafePerformIO $
ethjet_init >>= newForeignPtr ethjet_free
execute
:: Int
-> ByteString
-> Int
-> Maybe ByteString
execute contract input outputSize =
unsafePerformIO . BS.useAsCStringLen input $
\(inputPtr, inputSize) -> do
outputForeignPtr <- mallocForeignPtrBytes outputSize
withForeignPtr outputForeignPtr $ \outputPtr -> do
status <-
withForeignPtr globalContext $ \contextPtr ->
ethjet contextPtr (fromIntegral contract)
inputPtr (fromIntegral inputSize)
outputPtr (fromIntegral outputSize)
case status of
1 -> Just <$> BS.packCStringLen (outputPtr, outputSize)
_ -> pure Nothing