SkillAgentSearch skills...

CuEVM

Cuda implementation of EVM bytecode executor

Install / Use

/learn @sbip-sg/CuEVM
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CuEVM

Cuda implementation of EVM bytecode executor

Prerequisites

  • CUDA Toolkit (Version 12.0+, because we use --std c++20)
  • A CUDA-capable GPU (CUDA compute capabilily 7+ other older GPUs compability are not tested fully)
  • A C++ compiler compatible with the CUDA Toolkit (gcc/g++ version 10+)
  • For docker image, you don't need the above but the system with docker installed

Compile and Build binary

There are two methods, one requires installing all prequisited in the system, the second one use docker image:

On your own system

Building on Ubuntu (with sudo):

  • Setup required libraries: sudo apt install libgmp-dev
  • Setup cJSON: sudo apt install libcjson-dev
  • Use cmake to build the binary (Adjust -DCUDA_COMPUTE_CAPABILITY=86 according to your GPU compute capability number):
cmake -S . -B build -DTESTS=OFF -DGPU=ON -DCPU=OFF \
    -DCUDA_COMPUTE_CAPABILITY=86
    -DENABLE_EIP_3155_OPTIONAL=OFF \
    -DENABLE_EIP_3155=ON \
    -DENABLE_PAIRING_CODE=ON

cmake --build build

Building without sudo is also possible with extra configuration and modification on the Makefile or evironment variables, please refer to online tutorials on how to build and use libraries in custom directory

Building using docker image

  • Pull the docker image first: docker pull augustus/goevmlab-cuevm:20241008
  • Run and mount the current code folder docker run -it -v $(pwd):/workspaces/CuEVM augustus/goevmlab-cuevm:20241008
  • Inside the docker container, you can build the code using the same commands as above (Adjust -DCUDA_COMPUTE_CAPABILITY=86 according to your GPU compute capability number):
cmake -S . -B build -DTESTS=OFF -DGPU=ON -DCPU=OFF \
    -DCUDA_COMPUTE_CAPABILITY=86 \
    -DENABLE_EIP_3155_OPTIONAL=OFF \
    -DENABLE_EIP_3155=ON \
    -DENABLE_PAIRING_CODE=ON

cmake --build build

Usage

After building the binary, a binary named cuevm_GPU will be created in the build folder. You can run the binary using the following command:

./build/cuevmGPU --input [input_json_file]

For example:

./build/cuevm_GPU --input samples/underflowTest.json

The execution trace and output state will be printed to the stdout, you can use jq to keep only the Json output:

./build/cuevm_GPU --input samples/underflowTest.json \
    | jq -R 'select(try fromjson? | . != null) | fromjson'
{
  "pc": 0,
  "op": 97,
  "gas": "0x79bf20",
  "gasCost": "0x3",
  "memSize": 0,
  "stack": [],
  "depth": 1,
  "refund": 0
}
...

Demo of the GPU-accelerated fuzzer and CuEVM library mode

Run Google Colab demo using free GPU

Testing using ethtest

The script scripts/run-ethtest-by-fork can be used to run the tests from the ethereum/tests. It compares the traces from the outputs of CuEVM and geth without stateRoot.

Requirements:

The following will run all the tests in ethereum/tests/GeneralStateTests, note that this may take a few hours:

git clone --depth=1 --branch shanghai https://github.com/ethereum/tests.git ethereum/tests
python scripts/run-ethtest-by-fork.py --without-state-root --ignore-errors --microtests \
  --input ethereum/tests/GeneralStateTests/ \
  -t /tmp/ \
  --runtest-bin runtest \
  --geth geth \
  --cuevm build/cuevm_GPU

To run a single json test case in ethereum/tests, create a new folder and copy the json file to the new folder, for example,

mkdir my-test-folder
cp ethereum/tests/GeneralStateTests/Shanghai/stEIP3651-warmcoinbase/coinbaseWarmAccountCallGas.json my-test-folder/
python scripts/run-ethtest-by-fork.py --without-state-root --ignore-errors --microtests \
  --input my-test-folder/ \
  -t /tmp/ \
  --runtest-bin runtest \
  --geth geth \
  --cuevm build/cuevm_GPU

To inpsect the output from each EVM exeuctor, specify the path of the generated test file:

  • for go-ethereum:
geth --json --noreturndata --dump statetest {input_test_file}
# eg., geth --json --noreturndata --dump statetest /tmp/./coinbaseWarmAccountCallGas-0-0-0/coinbaseWarmAccountCallGas.json
  • for CuEVM
./build/cuevm_GPU --input {input_test_file}
# eg., ./build/cuevm_GPU --input /tmp/./coinbaseWarmAccountCallGas-0-0-0/coinbaseWarmAccountCallGas.json
  • to compare results between CuEVM and go-ethereum:
runtest --outdir=./ --geth=geth --cuevm=./build/cuevm_GPU /tmp/./coinbaseWarmAccountCallGas-0-0-0/coinbaseWarmAccountCallGas.json

Test results

Test results by comparing the traces between geth and cuevm without stateRoot comparison

We use the test files in Shanghai branch of ethereum/tests/GeneralStateTests to test whether we can get the same traces with the go-ethereum. To run the tests,

  • Build the cuevm_GPU binary
  • Either download or build the geth binary, in this test the version v1.13.14 is used, later version will probably produce the same result
  • Get the test json files from ethereum/tests: git clone --depth=1 --branch shanghai https://github.com/ethereum/tests.git ethereum/tests
  • Build the runtest binary from cassc/goevmlab which adds support for CuEVM
  • Run goevmlab/runtest to compare the results between geth and cuevm
  • The tests results are collected by running the Python script from the ethereum/tests root folder:
python ./run-ethtest-without-stateroot-comparison.py -t /tmp/out --runtest-bin runtest --geth geth --cuevm cuevm  --ignore-errors
  • Note that there can be multiple tests in one input json, the number of tests shown below can be larger than number of input json files.
  • Some tests are skipped if they do not support Shanghai VM.

| Test folder | Passed | Failed | Skipped | Timeout | |--------------------------------------|--------|--------|---------|---------| | stNonZeroCallsTest | 24 | 0 | 0 | 0 | | stEIP3607 | 12 | 0 | 0 | 0 | | stEIP150singleCodeGasPrices | 340 | 0 | 1 | 0 | | stCallDelegateCodesCallCodeHomestead | 57 | 1 | 0 | 0 | | stArgsZeroOneBalance | 96 | 0 | 0 | 0 | | stStaticFlagEnabled | 25 | 9 | 0 | 0 | | stShift | 40 | 0 | 0 | 2 | | stEIP158Specific | 7 | 0 | 0 | 0 | | stMemoryTest | 569 | 0 | 0 | 9 | | stZeroKnowledge2 | 519 | 0 | 0 | 0 | | stEIP1559 | 1841 | 4 | 0 | 0 | | stReturnDataTest | 260 | 13 | 0 | 0 | | stCodeCopyTest | 2 | 0 | 0 | 0 | | stMemoryStressTest | 80 | 2 | 0 | 0 | | stInitCodeTest | 22 | 0 | 0 | 0 | | stMemExpandingEIP150Calls | 9 | 1 | 0 | 0 | | stWalletTest | 20 | 26 | 0 | 0 | | stSpecialTest | 18 | 1 | 0 | 3 | | stExtCodeHash | 63 | 2 | 0 | 0 | | stTimeConsuming | 5187 | 0 | 0 | 3 | | stCreateTest | 168 | 31 | 0 | 4 | | stRecursiveCreate | 1 | 1 | 0 | 0 | | stCallDelegateCodesHomestead | 58 | 0 | 0 | 0 | | stZeroKnowledge | 751 | 49 | 0 | 0 | | stTransitionTest | 6 | 0 | 0 | 0 | | stCallCodes | 87 | 0 | 0 | 0 | | stHomesteadSpecific | 5 | 0 | 0 | 0 | | stCallCreateCallCodeTest | 41 | 2 | 0 | 12 | | stSolidityTest | 14 | 7 | 0 | 2 | | stExample | 38 | 1 | 0 | 0 | | stSStoreTest | 468 | 7 | 0 | 0 | | stZeroCallsTest | 24 | 0 | 0 | 0 | | stSelfBalance | 35 | 7 | 0 | 0 | | stDelegatecallTestHomestead | 23 | 0 | 0 | 8 | | stQuadraticComplexityTest | 12 | 2 | 0 | 18 | | stEIP150Specific | 25 | 0 | 0 | 0 | | stStackTests | 248 | 117 | 0 | 10 | | stChainId | 2 | 0 | 0 | 0 | | stAttackTest | 1 | 0 | 0 | 1 | | stBugs | 9 | 0 | 0 | 0 | | stBadOpcode | 3404 | 808 | 1 | 3 | | stTransactionTest | 164 | 0 | 0 | 0 | | stCreate2 | 182 | 3 | 0 | 5 | | stPreCompiledContracts2 | 247 | 0 | 0 | 1 | | stRevertTest | 257 | 4 | 0

View on GitHub
GitHub Stars118
CategoryDevelopment
Updated8d ago
Forks15

Languages

Cuda

Security Score

95/100

Audited on Mar 16, 2026

No findings