runtimeverification / evm-semantics

K Semantics of the Ethereum Virtual Machine (EVM)
BSD 3-Clause "New" or "Revised" License
509 stars 144 forks source link

KEVM: Semantics of EVM in K

In this repository, we provide a model of the EVM in K.

Fast Installation

NOTE: The first run will take longer to fetch all the libraries and compile sources. (30m to 1h)

Documentation/Support

These may be useful for learning KEVM and K (newest to oldest):

To get support for KEVM, please join our Discord Channel.

If you want to start proving with KEVM, refer to VERIFICATION.md.

Repository Structure

The following files constitute the KEVM semantics:

These additional files extend the semantics to make the repository more useful:

These files are used for testing the semantics itself:

Building from source

There are two backends of K available: LLVM for concrete execution and Haskell for symbolic execution. This repository generates the build-products for each backend in $XDG_CACHE_HOME/evm-semantics-<digest>.

System Dependencies

Run install-build-deps to install the required OS-supplied dependencies.

There are some additional notes for specific systems:

Ubuntu:

Arch:

MacOS:

Haskell Stack (all platforms)

To upgrade stack (if needed):

stack upgrade
export PATH=$HOME/.local/bin:$PATH

Build Dependencies

K Framework

You need to install the K Framework on your system, see the instructions there. The fastest way is via the kup package manager, with which you can do to get the correct version of K:

kup install k.openssl --version v$(cat deps/k_release)

You can also drop into a single development shell with the correct version of K on path by doing:

kup shell k.openssl --version v$(cat deps/k_release)

Building

First you need to set up a virtual environment using Poetry with the prerequisites python 3.8.*, pip >= 20.0.2, poetry >= 1.3.2:

make poetry

Blockchain Plugin

You also need to get the blockchain plugin submodule and install it.

git submodule update --init --recursive
poetry -C kevm-pyk run kdist --verbose build evm-semantics.plugin

To change the default compiler:

CXX=clang++-15 poetry -C kevm-pyk run kdist --verbose build evm-semantics.plugin

On Apple silicon:

APPLE_SILICON=true poetry -C kevm-pyk run kdist --verbose build evm-semantics.plugin

K Definitions

Finally, you can build the semantics.

poetry -C kevm-pyk run kdist --verbose build -j6

You can build specific targets using options evm-semantics.{llvm,kllvm,kllvm-runtime,haskell,haskell-standalone,plugin}, e.g.:

poetry -C kevm-pyk run kdist build -j2 evm-semantics.llvm evm-semantics.haskell

Targets can be cleaned with

poetry -C kevm-pyk run kdist clean

For more information, refer to kdist --help and the dist.py module.

Running Tests

To execute tests from the Ethereum Test Set, the submodule needs to be fetched first.

git submodule update --init --recursive  -- tests/ethereum-tests

The tests are run using the supplied Makefile.

The following subsume all other tests:

These are the individual test-suites (all of these can be suffixed with -all to also run slow tests):

All these targets call pytest under the hood. You can pass additional arguments to the call by appending them to variable PYTEST_ARGS. E.g. run

make test-vm PYTEST_ARGS+=-vv

to execute VMTests with increased verbosity, and

make test-vm PYTEST_ARGS+=-n0

to execute them on a single worker.

Files produced by test runs, e.g. kompiled definition and logs, can be found in /tmp/pytest-of-<user>/.

For Developers

If built from the source, the kevm-pyk executable will be installed in a virtual environment handled by Poetry. You can call kevm-pyk --help to get a quick summary of how to use the script.

Run the file tests/ethereum-tests/BlockchainTests/GeneralStateTests/VMTests/vmArithmeticTest/add0.json:

poetry -C kevm-pyk run kevm-pyk run tests/ethereum-tests/BlockchainTests/GeneralStateTests/VMTests/vmArithmeticTest/add0.json --schedule DEFAULT --mode VMTESTS

To enable the debug symbols for the llvm backend, build using this command:

poetry -C kevm-pyk run kdist build evm-semantics.llvm --arg enable-llvm-debug=true

To debug a conformance test, add the --debugger flag to the command:

poetry -C kevm-pyk run kevm-pyk run tests/ethereum-tests/BlockchainTests/GeneralStateTests/stExample/add11.json --target llvm --mode NORMAL --schedule SHANGHAI --chainid 1 --debugger

Keeping in mind while developing

Always have your build up-to-date.

Building with Nix

We now support building KEVM using nix flakes. To set up nix flakes you will need to be on nix 2.4 or higher and follow the instructions here.

For example, if you are on a standard Linux distribution, such as Ubuntu, first install nix and then enable flakes by editing either ~/.config/nix/nix.conf or /etc/nix/nix.conf and adding:

experimental-features = nix-command flakes

This is needed to expose the Nix 2.0 CLI and flakes support that are hidden behind feature-flags.

By default, Nix will build the project and its transitive dependencies from source, which can take up to an hour. We recommend setting up the binary cache to speed up the build process significantly.

To build KEVM, run:

nix build .#kevm

This will build all of KEVM and K and put a link to the resulting binaries in the result/ folder.

NOTE: Mac users, especially those running M1/M2 Macs may find nix segfaulting on occasion. If this happens, try running the nix command like this: GC_DONT_GC=1 nix build .

If you want to temporarily add the kevm binary to the current shell, run

nix shell .#kevm

Profiling with Nix

Nix can also be used to quickly profile different versions of the Haskell backend. Simply run:

nix build github:runtimeverification/evm-semantics#profile \
  --override-input k-framework/haskell-backend github:runtimeverification/haskell-backend/<HASH> \
  -o prof-<HASH>

replacing <HASH> with the commit you want to run profiling against.

If you want to profile against a working version of the Haskell backend repository, simply cd into the root of the repo and run:

nix build github:runtimeverification/evm-semantics#profile \
  --override-input k-framework/haskell-backend $(pwd) \
  -o prof-my-feature

To compare profiles, you can use:

nix run github:runtimeverification/evm-semantics#compare-profiles -- prof-my-feature prof-<HASH>

This will produce a nice table with the times for both versions of the haskell-backend. Note that #profile pre-pends the output of kore-exec --version to the profile run, which is then used as a tag by the #compare-profiles script. Therefore, any profiled local checkout of the haskell-backend will report as dirty-ghc8107 in the resulting table.

Media

This repository can build two pieces of documentation for you, the Jello Paper and the 2017 Devcon3 presentation.

System Dependencies

For the presentations in the media directory, you'll need pdflatex, commonly provided with texlive-full, and pandoc.

sudo apt install texlive-full pandoc

Building

To build all the PDFs (presentations and reports) available in the media/ directory, use:

make media

Resources

For more information about the K Framework, refer to these sources: