Skip to content

Commit bc4eefb

Browse files
authored
Merge PR #660: precompiles: Optionally use silkpre as implementation
Add CMake option (off by default) `EVMONE_PRECOMPILES_SILKPRE` to enable building of silkpre as the precompiles implementation.
2 parents 18a8972 + 3f06da2 commit bc4eefb

7 files changed

+196
-0
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ To build the evmone EVMC module (shared library), test, and benchmark:
8989
build/bin/evmone-bench test/evm-benchmarks/benchmarks
9090
```
9191

92+
### Precompiles
93+
94+
Ethereum Precompiled Contracts (_precompiles_ for short) are not directly supported by evmone.
95+
96+
However, there are options to enable limited precompiles support for testing.
97+
98+
1. The [test/state/precompiles_stub.json](./test/state/precompiles_stub.json) contains
99+
precompiles execution results for inputs commonly used in tests.
100+
You can use the precompiles STUB by setting the environment variable
101+
`EVMONE_PRECOMPILES_STUB=./test/state/precompiles_stub.json`.
102+
2. The CMake option `EVMONE_PRECOMPILES_SILKPRE=1` enables building of
103+
the [silkpre] third party library with the implementation of the precompiles.
104+
This library also requires [GMP] (e.g. libgmp-dev) library for building and execution.
105+
92106
### Tools
93107

94108
#### evm-test
@@ -138,10 +152,12 @@ Licensed under the [Apache License, Version 2.0].
138152
[EVMC]: https://github.com/ethereum/evmc
139153
[Ipsilon]: https://github.com/ipsilon
140154
[Ewasm]: https://github.com/ewasm
155+
[GMP]: https://gmplib.org
141156
[intx]: https://github.com/chfast/intx
142157
[ethash]: https://github.com/chfast/ethash
143158
[Releases]: https://github.com/ethereum/evmone/releases
144159
[standard readme]: https://github.com/RichardLitt/standard-readme
160+
[silkpre]: https://github.com/torquem-ch/silkpre
145161

146162
[appveyor badge]: https://img.shields.io/appveyor/ci/chfast/evmone/master.svg?logo=appveyor
147163
[circleci badge]: https://img.shields.io/circleci/project/github/ethereum/evmone/master.svg?logo=circleci

circle.yml

+22
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,27 @@ jobs:
485485
- upload_coverage:
486486
flags: statetests
487487

488+
precompiles-silkpre:
489+
executor: blockchain-tests
490+
environment:
491+
BUILD_TYPE: Coverage
492+
CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-Og -DEVMONE_PRECOMPILES_SILKPRE=1
493+
steps:
494+
- run:
495+
name: "Install GMP"
496+
command: sudo apt-get -q update && sudo apt-get -qy install libgmp-dev
497+
- build
498+
- download_execution_tests:
499+
rev: v12.2
500+
- run:
501+
name: "State tests"
502+
working_directory: ~/build
503+
command: |
504+
bin/evmone-statetest ~/tests/GeneralStateTests ~/tests/LegacyTests/Constantinople/GeneralStateTests
505+
- collect_coverage_gcc
506+
- upload_coverage:
507+
flags: statetests-silkpre
508+
488509
gcc-min:
489510
executor: linux-gcc-min
490511
steps:
@@ -666,6 +687,7 @@ workflows:
666687
tags:
667688
only: /^v[0-9].*/
668689
- state-tests
690+
- precompiles-silkpre
669691
- blockchain-tests
670692
- cmake-min
671693
- gcc-min

test/state/CMakeLists.txt

+30
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,33 @@ target_sources(
2828
state.hpp
2929
state.cpp
3030
)
31+
32+
option(EVMONE_PRECOMPILES_SILKPRE "Enable precompiles support via silkpre library" OFF)
33+
if(EVMONE_PRECOMPILES_SILKPRE)
34+
include(FetchContent)
35+
FetchContent_Declare(
36+
silkpre
37+
GIT_REPOSITORY https://github.com/torquem-ch/silkpre
38+
GIT_TAG 3322bb898ac9528fc2cf9a8df1e48360420d0c1a
39+
GIT_SHALLOW TRUE
40+
)
41+
set(BUILD_SHARED_LIBS_ORIG ${BUILD_SHARED_LIBS})
42+
set(BUILD_SHARED_LIBS OFF)
43+
FetchContent_MakeAvailable(silkpre)
44+
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_ORIG})
45+
46+
set_target_properties(
47+
silkpre secp256k1 ff
48+
PROPERTIES
49+
COMPILE_OPTIONS -w # Disable warnings.
50+
CXX_CLANG_TIDY ""
51+
)
52+
53+
target_link_libraries(evmone-state PRIVATE silkpre)
54+
target_compile_definitions(evmone-state PRIVATE EVMONE_PRECOMPILES_SILKPRE=1)
55+
target_sources(
56+
evmone-state PRIVATE
57+
precompiles_silkpre.hpp
58+
precompiles_silkpre.cpp
59+
)
60+
endif()

test/state/precompiles.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <limits>
1212
#include <unordered_map>
1313

14+
#ifdef EVMONE_PRECOMPILES_SILKPRE
15+
#include "precompiles_silkpre.hpp"
16+
#endif
17+
1418
namespace evmone::state
1519
{
1620
using namespace evmc::literals;
@@ -172,6 +176,16 @@ inline constexpr auto traits = []() noexcept {
172176
{ecpairing_analyze, dummy_execute<PrecompileId::ecpairing>},
173177
{blake2bf_analyze, dummy_execute<PrecompileId::blake2bf>},
174178
}};
179+
#ifdef EVMONE_PRECOMPILES_SILKPRE
180+
tbl[static_cast<size_t>(PrecompileId::ecrecover)].execute = silkpre_ecrecover_execute;
181+
tbl[static_cast<size_t>(PrecompileId::sha256)].execute = silkpre_sha256_execute;
182+
tbl[static_cast<size_t>(PrecompileId::ripemd160)].execute = silkpre_ripemd160_execute;
183+
tbl[static_cast<size_t>(PrecompileId::expmod)].execute = silkpre_expmod_execute;
184+
tbl[static_cast<size_t>(PrecompileId::ecadd)].execute = silkpre_ecadd_execute;
185+
tbl[static_cast<size_t>(PrecompileId::ecmul)].execute = silkpre_ecmul_execute;
186+
tbl[static_cast<size_t>(PrecompileId::ecpairing)].execute = silkpre_ecpairing_execute;
187+
tbl[static_cast<size_t>(PrecompileId::blake2bf)].execute = silkpre_blake2bf_execute;
188+
#endif
175189
return tbl;
176190
}();
177191
} // namespace

test/state/precompiles_silkpre.cpp

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2022 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "precompiles_silkpre.hpp"
6+
#include <silkpre/precompile.h>
7+
#include <cassert>
8+
#include <cstring>
9+
10+
namespace evmone::state
11+
{
12+
namespace
13+
{
14+
ExecutionResult execute(const uint8_t* input, size_t input_size, uint8_t* output_buf,
15+
[[maybe_unused]] size_t max_output_size, PrecompileId id) noexcept
16+
{
17+
const auto index = stdx::to_underlying(id) - 1;
18+
const auto [output, output_size] = kSilkpreContracts[index].run(input, input_size);
19+
if (output == nullptr)
20+
return {EVMC_PRECOMPILE_FAILURE, 0};
21+
22+
// Check if max_output_size computed by analysis match the computed result.
23+
assert(output_size <= max_output_size);
24+
25+
const auto trimmed_output_size = std::min(output_size, max_output_size);
26+
std::memcpy(output_buf, output, trimmed_output_size);
27+
std::free(output); // Free output allocation (required by silkpre API).
28+
return {EVMC_SUCCESS, trimmed_output_size};
29+
}
30+
} // namespace
31+
32+
ExecutionResult silkpre_ecrecover_execute(
33+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
34+
{
35+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecrecover);
36+
}
37+
38+
ExecutionResult silkpre_sha256_execute(
39+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
40+
{
41+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::sha256);
42+
}
43+
44+
ExecutionResult silkpre_ripemd160_execute(
45+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
46+
{
47+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::ripemd160);
48+
}
49+
50+
ExecutionResult silkpre_expmod_execute(
51+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
52+
{
53+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::expmod);
54+
}
55+
56+
ExecutionResult silkpre_ecadd_execute(
57+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
58+
{
59+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecadd);
60+
}
61+
62+
ExecutionResult silkpre_ecmul_execute(
63+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
64+
{
65+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecmul);
66+
}
67+
68+
69+
ExecutionResult silkpre_ecpairing_execute(
70+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
71+
{
72+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::ecpairing);
73+
}
74+
75+
ExecutionResult silkpre_blake2bf_execute(
76+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept
77+
{
78+
return execute(input, input_size, output_buf, max_output_size, PrecompileId::blake2bf);
79+
}
80+
} // namespace evmone::state

test/state/precompiles_silkpre.hpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2022 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
#pragma once
5+
6+
#include "precompiles.hpp"
7+
8+
namespace evmone::state
9+
{
10+
ExecutionResult silkpre_ecrecover_execute(
11+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
12+
13+
ExecutionResult silkpre_sha256_execute(
14+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
15+
16+
ExecutionResult silkpre_ripemd160_execute(
17+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
18+
19+
ExecutionResult silkpre_expmod_execute(
20+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
21+
22+
ExecutionResult silkpre_ecadd_execute(
23+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
24+
25+
ExecutionResult silkpre_ecmul_execute(
26+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
27+
28+
ExecutionResult silkpre_ecpairing_execute(
29+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
30+
31+
ExecutionResult silkpre_blake2bf_execute(
32+
const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept;
33+
} // namespace evmone::state

test/state/precompiles_stub.json

+1
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@
668668
},
669669
{
670670
"0537dab8bcfa337395fdfbd203d054ac25c08722e9416a0ac259b779a2c87721": "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923",
671+
"05bd989b8f157e23dbb02b8bc54d344a60558de44a7ee3f804cf1dfc9e82bbda": "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615",
671672
"13d12ef157bef72bdae72d1981ac6bc16ab74176742f7fb689ecef08d3d6bf0d": "d82c6a670dc90af9d7f77644eacbeddfed91b760c65c927871784abceaab3f813759733a1736254fb1cfc515dbfee467930955af56e27ee435f836fc3e65969f",
672673
"2699f65d0bde17d17b834840e823616c33fb78e1a63f31fb6613bd1b08b888b4": "68790ca7594dd6fc28f0a86b7ddce0a225a8ea8fc2637f910eb71f6e54d9f8fa3e6302691015f11b15b755076d316823e6ce2ee4dd4aef60efc9189f6bd21bfd",
673674
"30e40ece3441a7de9a9451e74fab98b455c4823f2485b2373a43a8b6c928a9fb": null,

0 commit comments

Comments
 (0)