From 809bdb40bc4b2beac2331eca1b973fe71bfa82b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 17 Jun 2022 22:05:04 +0200 Subject: [PATCH 1/5] cmake: Optionally fetch silkpre library Add CMake option EVMONE_PRECOMPILES_SILKPRE (default OFF). If enabled CMake will fetch the silkpre precompiles library. https://github.com/torquem-ch/silkpre --- test/state/CMakeLists.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/state/CMakeLists.txt b/test/state/CMakeLists.txt index 1c152f8238..09b035f82a 100644 --- a/test/state/CMakeLists.txt +++ b/test/state/CMakeLists.txt @@ -28,3 +28,28 @@ target_sources( state.hpp state.cpp ) + +option(EVMONE_PRECOMPILES_SILKPRE "Enable precompiles support via silkpre library" OFF) +if(EVMONE_PRECOMPILES_SILKPRE) + include(FetchContent) + FetchContent_Declare( + silkpre + GIT_REPOSITORY https://github.com/torquem-ch/silkpre + GIT_TAG 3322bb898ac9528fc2cf9a8df1e48360420d0c1a + GIT_SHALLOW TRUE + ) + set(BUILD_SHARED_LIBS_ORIG ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS OFF) + FetchContent_MakeAvailable(silkpre) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_ORIG}) + + set_target_properties( + silkpre secp256k1 ff + PROPERTIES + COMPILE_OPTIONS -w # Disable warnings. + CXX_CLANG_TIDY "" + ) + + target_link_libraries(evmone-state PRIVATE silkpre) + target_compile_definitions(evmone-state PRIVATE EVMONE_PRECOMPILES_SILKPRE=1) +endif() From 548ec9271f9431ef7d6622aeb4ea782f7e3a7429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 1 Aug 2022 13:29:30 +0200 Subject: [PATCH 2/5] precompiles: Optionally use silkpre as implementation --- test/state/CMakeLists.txt | 5 ++ test/state/precompiles.cpp | 14 ++++++ test/state/precompiles_silkpre.cpp | 80 ++++++++++++++++++++++++++++++ test/state/precompiles_silkpre.hpp | 33 ++++++++++++ 4 files changed, 132 insertions(+) create mode 100644 test/state/precompiles_silkpre.cpp create mode 100644 test/state/precompiles_silkpre.hpp diff --git a/test/state/CMakeLists.txt b/test/state/CMakeLists.txt index 09b035f82a..9d569084d5 100644 --- a/test/state/CMakeLists.txt +++ b/test/state/CMakeLists.txt @@ -52,4 +52,9 @@ if(EVMONE_PRECOMPILES_SILKPRE) target_link_libraries(evmone-state PRIVATE silkpre) target_compile_definitions(evmone-state PRIVATE EVMONE_PRECOMPILES_SILKPRE=1) + target_sources( + evmone-state PRIVATE + precompiles_silkpre.hpp + precompiles_silkpre.cpp + ) endif() diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 47c9b81b16..75a06e5aaf 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -11,6 +11,10 @@ #include #include +#ifdef EVMONE_PRECOMPILES_SILKPRE +#include "precompiles_silkpre.hpp" +#endif + namespace evmone::state { using namespace evmc::literals; @@ -172,6 +176,16 @@ inline constexpr auto traits = []() noexcept { {ecpairing_analyze, dummy_execute}, {blake2bf_analyze, dummy_execute}, }}; +#ifdef EVMONE_PRECOMPILES_SILKPRE + tbl[static_cast(PrecompileId::ecrecover)].execute = silkpre_ecrecover_execute; + tbl[static_cast(PrecompileId::sha256)].execute = silkpre_sha256_execute; + tbl[static_cast(PrecompileId::ripemd160)].execute = silkpre_ripemd160_execute; + tbl[static_cast(PrecompileId::expmod)].execute = silkpre_expmod_execute; + tbl[static_cast(PrecompileId::ecadd)].execute = silkpre_ecadd_execute; + tbl[static_cast(PrecompileId::ecmul)].execute = silkpre_ecmul_execute; + tbl[static_cast(PrecompileId::ecpairing)].execute = silkpre_ecpairing_execute; + tbl[static_cast(PrecompileId::blake2bf)].execute = silkpre_blake2bf_execute; +#endif return tbl; }(); } // namespace diff --git a/test/state/precompiles_silkpre.cpp b/test/state/precompiles_silkpre.cpp new file mode 100644 index 0000000000..7ca9966c70 --- /dev/null +++ b/test/state/precompiles_silkpre.cpp @@ -0,0 +1,80 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2022 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include "precompiles_silkpre.hpp" +#include +#include +#include + +namespace evmone::state +{ +namespace +{ +ExecutionResult execute(const uint8_t* input, size_t input_size, uint8_t* output_buf, + [[maybe_unused]] size_t max_output_size, PrecompileId id) noexcept +{ + const auto index = stdx::to_underlying(id) - 1; + const auto [output, output_size] = kSilkpreContracts[index].run(input, input_size); + if (output == nullptr) + return {EVMC_PRECOMPILE_FAILURE, 0}; + + // Check if max_output_size computed by analysis match the computed result. + assert(output_size <= max_output_size); + + const auto trimmed_output_size = std::min(output_size, max_output_size); + std::memcpy(output_buf, output, trimmed_output_size); + std::free(output); // Free output allocation (required by silkpre API). + return {EVMC_SUCCESS, trimmed_output_size}; +} +} // namespace + +ExecutionResult silkpre_ecrecover_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecrecover); +} + +ExecutionResult silkpre_sha256_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::sha256); +} + +ExecutionResult silkpre_ripemd160_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::ripemd160); +} + +ExecutionResult silkpre_expmod_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::expmod); +} + +ExecutionResult silkpre_ecadd_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecadd); +} + +ExecutionResult silkpre_ecmul_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecmul); +} + + +ExecutionResult silkpre_ecpairing_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecpairing); +} + +ExecutionResult silkpre_blake2bf_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept +{ + return execute(input, input_size, output_buf, max_output_size, PrecompileId::blake2bf); +} +} // namespace evmone::state diff --git a/test/state/precompiles_silkpre.hpp b/test/state/precompiles_silkpre.hpp new file mode 100644 index 0000000000..b6d2d48c61 --- /dev/null +++ b/test/state/precompiles_silkpre.hpp @@ -0,0 +1,33 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2022 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include "precompiles.hpp" + +namespace evmone::state +{ +ExecutionResult silkpre_ecrecover_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_sha256_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_ripemd160_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_expmod_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_ecadd_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_ecmul_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_ecpairing_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; + +ExecutionResult silkpre_blake2bf_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; +} // namespace evmone::state From c50f3df66beecca9c03cca1a5ffe2da05bda17cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sun, 23 Jul 2023 19:05:45 +0200 Subject: [PATCH 3/5] precompiles: Add one more blake2b stub entry This is from the stTimeConsuming.CALLBlake2f_MaxRounds state test. --- test/state/precompiles_stub.json | 1 + 1 file changed, 1 insertion(+) diff --git a/test/state/precompiles_stub.json b/test/state/precompiles_stub.json index 2d15618a7d..4b1dbb86b0 100644 --- a/test/state/precompiles_stub.json +++ b/test/state/precompiles_stub.json @@ -668,6 +668,7 @@ }, { "0537dab8bcfa337395fdfbd203d054ac25c08722e9416a0ac259b779a2c87721": "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", + "05bd989b8f157e23dbb02b8bc54d344a60558de44a7ee3f804cf1dfc9e82bbda": "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615", "13d12ef157bef72bdae72d1981ac6bc16ab74176742f7fb689ecef08d3d6bf0d": "d82c6a670dc90af9d7f77644eacbeddfed91b760c65c927871784abceaab3f813759733a1736254fb1cfc515dbfee467930955af56e27ee435f836fc3e65969f", "2699f65d0bde17d17b834840e823616c33fb78e1a63f31fb6613bd1b08b888b4": "68790ca7594dd6fc28f0a86b7ddce0a225a8ea8fc2637f910eb71f6e54d9f8fa3e6302691015f11b15b755076d316823e6ce2ee4dd4aef60efc9189f6bd21bfd", "30e40ece3441a7de9a9451e74fab98b455c4823f2485b2373a43a8b6c928a9fb": null, From cf5e881606198d5df5a5411a15d92b665a2a8df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 24 Jul 2023 11:01:42 +0200 Subject: [PATCH 4/5] ci: Test silkpre precompiles --- circle.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/circle.yml b/circle.yml index 5aa179807c..a6b64df3f2 100644 --- a/circle.yml +++ b/circle.yml @@ -485,6 +485,27 @@ jobs: - upload_coverage: flags: statetests + precompiles-silkpre: + executor: blockchain-tests + environment: + BUILD_TYPE: Coverage + CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-Og -DEVMONE_PRECOMPILES_SILKPRE=1 + steps: + - run: + name: "Install GMP" + command: sudo apt-get -q update && sudo apt-get -qy install libgmp-dev + - build + - download_execution_tests: + rev: v12.2 + - run: + name: "State tests" + working_directory: ~/build + command: | + bin/evmone-statetest ~/tests/GeneralStateTests ~/tests/LegacyTests/Constantinople/GeneralStateTests + - collect_coverage_gcc + - upload_coverage: + flags: statetests-silkpre + gcc-min: executor: linux-gcc-min steps: @@ -666,6 +687,7 @@ workflows: tags: only: /^v[0-9].*/ - state-tests + - precompiles-silkpre - blockchain-tests - cmake-min - gcc-min From 3f06da2740cb67db5345a29af38085c641118d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 28 Jul 2023 12:31:38 +0200 Subject: [PATCH 5/5] readme: Add section about precompiles support --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 84bf191d83..d74962b5f6 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,20 @@ To build the evmone EVMC module (shared library), test, and benchmark: build/bin/evmone-bench test/evm-benchmarks/benchmarks ``` +### Precompiles + +Ethereum Precompiled Contracts (_precompiles_ for short) are not directly supported by evmone. + +However, there are options to enable limited precompiles support for testing. + +1. The [test/state/precompiles_stub.json](./test/state/precompiles_stub.json) contains + precompiles execution results for inputs commonly used in tests. + You can use the precompiles STUB by setting the environment variable + `EVMONE_PRECOMPILES_STUB=./test/state/precompiles_stub.json`. +2. The CMake option `EVMONE_PRECOMPILES_SILKPRE=1` enables building of + the [silkpre] third party library with the implementation of the precompiles. + This library also requires [GMP] (e.g. libgmp-dev) library for building and execution. + ### Tools #### evm-test @@ -138,10 +152,12 @@ Licensed under the [Apache License, Version 2.0]. [EVMC]: https://github.com/ethereum/evmc [Ipsilon]: https://github.com/ipsilon [Ewasm]: https://github.com/ewasm +[GMP]: https://gmplib.org [intx]: https://github.com/chfast/intx [ethash]: https://github.com/chfast/ethash [Releases]: https://github.com/ethereum/evmone/releases [standard readme]: https://github.com/RichardLitt/standard-readme +[silkpre]: https://github.com/torquem-ch/silkpre [appveyor badge]: https://img.shields.io/appveyor/ci/chfast/evmone/master.svg?logo=appveyor [circleci badge]: https://img.shields.io/circleci/project/github/ethereum/evmone/master.svg?logo=circleci