Compare commits
348 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3957a55641 | |||
| 01cdc2423d | |||
| 99e4c4e669 | |||
| 422251466c | |||
| 18bfc53964 | |||
| 11fe3fb262 | |||
| e6f84d85d2 | |||
| fa635449fb | |||
| e682c99cec | |||
| 2aaa7abe94 | |||
| 84cd74a1c5 | |||
| e16a17114c | |||
| 5e4134da93 | |||
| f1a60adff0 | |||
| 71a2f1135f | |||
| 70762315c9 | |||
| 53c462bf09 | |||
| 5d3689d9b4 | |||
| 17c9ef5c3d | |||
| 7d5c3c9f70 | |||
| ed1068b411 | |||
| ccf35ef625 | |||
| 6b2ae8e72e | |||
| 58e4c327cc | |||
| 7312368096 | |||
| 7790b4618d | |||
| 87359e262a | |||
| 339853d3f5 | |||
| 9b948c0150 | |||
| ae0439ba8c | |||
| 4dcb8318a3 | |||
| b92b997c6b | |||
| 59ee6ed2ee | |||
| bf33fdabea | |||
| fab0b7c793 | |||
| b52647b2c9 | |||
| 8d2637e6a5 | |||
| 27573c7724 | |||
| 0c4352e821 | |||
| 91af790fca | |||
| 7b77458c9a | |||
| 2b64357ccb | |||
| 4d11419160 | |||
| 88a34cd9b4 | |||
| 216534d5e9 | |||
| cabcc2fe3a | |||
| aba2cdfcce | |||
| 59ba45da4e | |||
| 905c5cc900 | |||
| 8d1b8a5698 | |||
| 3297d97a43 | |||
| f922a86ab0 | |||
| 0ed399830f | |||
| 8540836ffe | |||
| fa94b49279 | |||
| 9497c0897a | |||
| a9ef9fff63 | |||
| 2fdb55e340 | |||
| aab82cdc40 | |||
| a92fd7cb16 | |||
| 2d96bfe3b2 | |||
| bb531f373e | |||
| 1120377466 | |||
| e0ecbb649f | |||
| 20b0d9d60e | |||
| 47012ce342 | |||
| 2b03bff637 | |||
| 9003617853 | |||
| 46df41c112 | |||
| b1c6847a75 | |||
| 62dd2b0b94 | |||
| 17932b2bb8 | |||
| f5d8814efb | |||
| 38958de461 | |||
| 1e9587826c | |||
| 295ef4a3c5 | |||
| 6a6d8ddceb | |||
| a96e206b3b | |||
| aa09279bab | |||
| 5c0916707e | |||
| d64431867e | |||
| a7ad638eb6 | |||
| 0f4ad02f85 | |||
| 1ee599636a | |||
| cc2513cdb4 | |||
| bc5b1daaff | |||
| 7ddf820603 | |||
| 5da9f20157 | |||
| be11b99340 | |||
| 4323406aba | |||
| 15aaa7f2ec | |||
| 8175ac9657 | |||
| fd4a7042f3 | |||
| 574ebb0a06 | |||
| 51fe9c6e4f | |||
| 4c305088ac | |||
| e5bb8b2151 | |||
| 645c15b4c9 | |||
| 8af31a80c1 | |||
| 70fca6820e | |||
| 43d89c42ea | |||
| 6ecf3db344 | |||
| 80d75b7ecc | |||
| feb14eee57 | |||
| aa7d8a6f17 | |||
| ec3b6fb901 | |||
| f03ac3c127 | |||
| 88a7d105a5 | |||
| 090bb3b84a | |||
| a4725084f7 | |||
| 14e8744a16 | |||
| 3d3c6f3f83 | |||
| 8949432a55 | |||
| e512ae876f | |||
| 8ef7391c59 | |||
| 3fb64777d6 | |||
| d15b62c0c7 | |||
| 4f35faef9e | |||
| c2d07777bb | |||
| ff7f7ea49e | |||
| ca8017529d | |||
| d3e857e8c8 | |||
| 1476c1fdc8 | |||
| d45e97b5d1 | |||
| 6e4e403597 | |||
| 2d65bf203e | |||
| f10f289b08 | |||
| 65f5209e97 | |||
| d372c2e94f | |||
| cb225377ac | |||
| b4b029d189 | |||
| 91edd31d9f | |||
| 153ad0d84b | |||
| efdbb176e5 | |||
| 9fc59835eb | |||
| 9d52949b37 | |||
| 6292407a59 | |||
| a72f980728 | |||
| 39a6347310 | |||
| 6015686b31 | |||
| 0f1b594a9d | |||
| 0e6b4e969d | |||
| 36ac6e0ed7 | |||
| 9f0e9d9eb8 | |||
| c4d4562121 | |||
| 1aa9995e79 | |||
| ccb509fedd | |||
| 8edc3f1fc6 | |||
| 772392df5b | |||
| c9a2bfff94 | |||
| 13004af9e3 | |||
| d5edd70f99 | |||
| ae00005127 | |||
| cb3ccfc739 | |||
| 94fe8787f9 | |||
| c023d3a837 | |||
| 7caf43059a | |||
| 3c1079c812 | |||
| 69c3db06a9 | |||
| 2e9cffa2ff | |||
| f41cddc690 | |||
| c3d3a02be2 | |||
| 04e9472e30 | |||
| f313860ce1 | |||
| 455b6558f9 | |||
| ebb14d15d0 | |||
| 18ba34d98e | |||
| c4260e1cba | |||
| b0ccf805ae | |||
| 6ecc162e69 | |||
| be063ffe81 | |||
| 030b062fd7 | |||
| b6eee20fad | |||
| 0d0fa9bd9d | |||
| 71fa65ed21 | |||
| 30e66efc3a | |||
| 43e8d542fd | |||
| adeb2ebb40 | |||
| 1987bfb87b | |||
| bbc010d530 | |||
| 824f2e4c4f | |||
| 024c00c653 | |||
| 1b41777178 | |||
| 8676c48c79 | |||
| eff27476f2 | |||
| ffc4fed389 | |||
| 0b503d8af1 | |||
| 3ea1153568 | |||
| a6e466d12c | |||
| 0cf008b736 | |||
| 3a802a50a8 | |||
| 8ef4d9ae63 | |||
| 120b8a218f | |||
| 8ca4c2e797 | |||
| 0dc0bf04fa | |||
| 8add1de424 | |||
| cebdaeea38 | |||
| 1a7de9a784 | |||
| a53baae5e1 | |||
| f2a152b533 | |||
| 3d7b806b6e | |||
| f1d4e091c6 | |||
| 3d2a856422 | |||
| 6c4934d018 | |||
| 1fcc038f73 | |||
| 1568db3d04 | |||
| a64414ba8e | |||
| 7a3219c57f | |||
| 79e88acc60 | |||
| 17e5d327ff | |||
| 5f30678870 | |||
| a227fe76c8 | |||
| aa029c5849 | |||
| 6500d09c6f | |||
| 4a72240b32 | |||
| 316c0d5859 | |||
| 5dc6da40ea | |||
| 2ad4acf711 | |||
| c22ec81513 | |||
| 8c922dc690 | |||
| ce6ce28931 | |||
| af52c2f891 | |||
| 1bb8e2b709 | |||
| 4899513084 | |||
| fef16099ce | |||
| bebd6a03fa | |||
| 6f5f2bcabc | |||
| abcbc7e927 | |||
| 4bc7fed862 | |||
| ebf9c8c168 | |||
| 28c9f25dd1 | |||
| d9ad5a3bf3 | |||
| 7b4349970e | |||
| 86093fb892 | |||
| a9e27cc641 | |||
| bc5ecd4b7d | |||
| 56e45f74c1 | |||
| 65f169a224 | |||
| f74dfa7d8c | |||
| 1d634e1c54 | |||
| bb55a758cc | |||
| 63857ce274 | |||
| fef8e5ae51 | |||
| 9ff810e580 | |||
| dc3d83988b | |||
| 0b3d134ea0 | |||
| 7aeaedd466 | |||
| a63c57aa35 | |||
| 57da493022 | |||
| 817cabb105 | |||
| 3ae4b7d434 | |||
| 6ddcfd6d45 | |||
| f4ea2f28f1 | |||
| d5a73f15b7 | |||
| 6a283dca85 | |||
| 62f37bc9f9 | |||
| 580ace4647 | |||
| c886c212a2 | |||
| b2943c1466 | |||
| d12d09dc8c | |||
| f28a665d72 | |||
| 79960fa885 | |||
| a568762735 | |||
| 4c44ce9d01 | |||
| 7feb2dfb1b | |||
| bd6f14b923 | |||
| cc18180eb5 | |||
| 5465066b77 | |||
| 7bdc7bba98 | |||
| a08fe0a427 | |||
| a6d26d638a | |||
| 03806436eb | |||
| 2069c845e6 | |||
| f155ed0011 | |||
| 41607c227a | |||
| b01fcdd233 | |||
| d6a6fb5c43 | |||
| 9fa0fe01b2 | |||
| e18d60dfed | |||
| 8ac8a255a1 | |||
| 36deb3b29d | |||
| 26cbf288fe | |||
| cbdea09fbc | |||
| 30d6eeb491 | |||
| 5f71755811 | |||
| d486d0a6f2 | |||
| 58a8cc5228 | |||
| 3d4e760e55 | |||
| b98792a84e | |||
| 0ddaae68e8 | |||
| 3a991b8419 | |||
| 11a8715bee | |||
| 4f91b67774 | |||
| 23f7cc47c4 | |||
| 8a94b88d32 | |||
| 4890d44339 | |||
| a7bc33b939 | |||
| 97055bcc90 | |||
| 9916ba70ea | |||
| 9da843f749 | |||
| 7db26d8cb7 | |||
| 665c70e56e | |||
| fa5bcff358 | |||
| 5f99b993cd | |||
| f27a3fdc44 | |||
| ff38254c95 | |||
| 4bbc139630 | |||
| 2683386aa5 | |||
| ca93161f2f | |||
| fd1b3c81ad | |||
| a3ed3feb2c | |||
| 88812e5257 | |||
| 950834731b | |||
| 0172dc055f | |||
| 28bf15af35 | |||
| 5100f44b46 | |||
| cd80859b12 | |||
| 50a662db4b | |||
| ddd135bf22 | |||
| 815189eba8 | |||
| d8b3167498 | |||
| fcfe827615 | |||
| 4f03913543 | |||
| 4cd534a148 | |||
| fce62ceff5 | |||
| c877b1e78b | |||
| 81c088f567 | |||
| f4f5d1814d | |||
| 3c56203544 | |||
| 2b9a2a87f8 | |||
| 714a0a929a | |||
| 05fda58d33 | |||
| 9077f9bbe2 | |||
| c1f8889088 | |||
| b0c409a2f8 | |||
| dc13e7271d | |||
| 60cedbc26b | |||
| e11e7dddca | |||
| 0b64f879e3 | |||
| 7f017d5590 | |||
| 2b5140489c | |||
| ae853b4586 | |||
| f80e29ecec | |||
| 050dbd82f7 | |||
| fa4e5ef0c2 | |||
| ed1d8dafcc | |||
| 926cc4e509 | |||
| 6eeb2d15ac |
@@ -7,13 +7,10 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
g++-8 \
|
||||
git \
|
||||
jq \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
python3 \
|
||||
software-properties-common \
|
||||
zlib1g-dev \
|
||||
|
||||
@@ -7,11 +7,8 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
git \
|
||||
jq \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
zstd
|
||||
|
||||
@@ -7,11 +7,8 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
git \
|
||||
jq \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
zstd
|
||||
|
||||
@@ -12,6 +12,7 @@ jobs:
|
||||
label: triage
|
||||
org-project: 'Team Backlog'
|
||||
project-field: Status=Todo
|
||||
skip-if-existing-project: true
|
||||
secrets:
|
||||
token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}}
|
||||
|
||||
|
||||
+4
-2
@@ -77,8 +77,9 @@ witness_node_data_dir
|
||||
|
||||
Testing/*
|
||||
build.tar.gz
|
||||
build/*
|
||||
build-debug/*
|
||||
[Bb]uild*/*
|
||||
deps/*
|
||||
dependencies/*
|
||||
|
||||
etc/eosio/node_*
|
||||
var/lib/node_*
|
||||
@@ -86,6 +87,7 @@ var/lib/node_*
|
||||
.idea/
|
||||
*.iws
|
||||
.DS_Store
|
||||
CMakeLists.txt.user
|
||||
|
||||
!*.swagger.*
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
[submodule "libraries/rapidjson"]
|
||||
path = libraries/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson/
|
||||
[submodule "libraries/yubihsm"]
|
||||
path = libraries/yubihsm
|
||||
url = https://github.com/Yubico/yubihsm-shell
|
||||
[submodule "tests/abieos"]
|
||||
path = tests/abieos
|
||||
url = https://github.com/AntelopeIO/abieos
|
||||
@@ -28,6 +25,3 @@
|
||||
[submodule "libraries/libfc/libraries/ff"]
|
||||
path = libraries/libfc/libraries/ff
|
||||
url = https://github.com/AntelopeIO/libff
|
||||
[submodule "libraries/prometheus-cpp"]
|
||||
path = libraries/prometheus-cpp
|
||||
url = https://github.com/jupp0r/prometheus-cpp.git
|
||||
|
||||
+18
-8
@@ -13,8 +13,8 @@ set( CMAKE_CXX_STANDARD 17 )
|
||||
set( CMAKE_CXX_EXTENSIONS ON )
|
||||
set( CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(VERSION_MAJOR 3)
|
||||
set(VERSION_MINOR 2)
|
||||
set(VERSION_MAJOR 4)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_SUFFIX dev)
|
||||
|
||||
@@ -24,6 +24,12 @@ else()
|
||||
set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
endif()
|
||||
|
||||
|
||||
# Options
|
||||
option(ENABLE_WERROR "Enable `-Werror` compilation flag." Off)
|
||||
option(ENABLE_WEXTRA "Enable `-Wextra` compilation flag." Off)
|
||||
|
||||
|
||||
set( CLI_CLIENT_EXECUTABLE_NAME cleos )
|
||||
set( NODE_EXECUTABLE_NAME nodeos )
|
||||
set( KEY_STORE_EXECUTABLE_NAME keosd )
|
||||
@@ -60,8 +66,6 @@ if(APPLE AND UNIX AND "${OPENSSL_ROOT_DIR}" STREQUAL "")
|
||||
set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@3;/usr/local/opt/openssl@1.1")
|
||||
endif()
|
||||
endif()
|
||||
# fc also adds these definitions to its public interface. once fc becomes the sole importer of openssl, this should be removed
|
||||
add_definitions(-DOPENSSL_API_COMPAT=0x10100000L -DOPENSSL_NO_DEPRECATED)
|
||||
|
||||
option(ENABLE_OC "Enable eosvm-oc on supported platforms" ON)
|
||||
|
||||
@@ -128,6 +132,16 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_WERROR)
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror" )
|
||||
endif()
|
||||
if(ENABLE_WEXTRA)
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra" )
|
||||
endif()
|
||||
|
||||
|
||||
option(EOSIO_ENABLE_DEVELOPER_OPTIONS "enable developer options for Leap" OFF)
|
||||
|
||||
# based on http://www.delorie.com/gnu/docs/gdb/gdb_70.html
|
||||
@@ -224,7 +238,6 @@ configure_file(libraries/libfc/src/network/LICENSE.go licen
|
||||
configure_file(libraries/eos-vm/LICENSE licenses/leap/LICENSE.eos-vm COPYONLY)
|
||||
configure_file(libraries/libfc/libraries/ff/LICENSE licenses/leap/LICENSE.libff COPYONLY)
|
||||
configure_file(programs/cleos/LICENSE.CLI11 licenses/leap/LICENSE.CLI11 COPYONLY)
|
||||
configure_file(libraries/yubihsm/LICENSE licenses/leap/LICENSE.yubihsm COPYONLY)
|
||||
|
||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/licenses/leap" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/" COMPONENT base)
|
||||
|
||||
@@ -243,9 +256,6 @@ add_custom_target(dev-install
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE)
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "SET(CTEST_CUSTOM_TESTS_IGNORE ${_CTEST_CUSTOM_TESTS_IGNORE})")
|
||||
|
||||
include(doxygen)
|
||||
|
||||
include(package.cmake)
|
||||
|
||||
@@ -51,7 +51,7 @@ find_package(Boost @Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@ EXACT REQUIRED CO
|
||||
|
||||
find_library(libtester eosio_testing @CMAKE_BINARY_DIR@/libraries/testing NO_DEFAULT_PATH)
|
||||
find_library(libchain eosio_chain @CMAKE_BINARY_DIR@/libraries/chain NO_DEFAULT_PATH)
|
||||
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/fc NO_DEFAULT_PATH)
|
||||
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/libfc NO_DEFAULT_PATH)
|
||||
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/libfc/secp256k1 NO_DEFAULT_PATH)
|
||||
|
||||
find_library(libff ff @CMAKE_BINARY_DIR@/libraries/libfc/libraries/ff/libff NO_DEFAULT_PATH)
|
||||
|
||||
@@ -1,126 +1,249 @@
|
||||
# Leap
|
||||
Leap is a C++ implementation of the [Antelope](https://github.com/AntelopeIO) protocol. It contains blockchain node software and supporting tools for developers and node operators.
|
||||
|
||||
Leap is blockchain node software and supporting tools that implements the [Antelope](https://github.com/AntelopeIO) protocol.
|
||||
## Branches
|
||||
The `main` branch is the development branch; do not use it for production. Refer to the [release page](https://github.com/AntelopeIO/leap/releases) for current information on releases, pre-releases, and obsolete releases, as well as the corresponding tags for those releases.
|
||||
|
||||
## Repo Organization
|
||||
## Supported Operating Systems
|
||||
We currently support the following operating systems.
|
||||
- Ubuntu 22.04 Jammy
|
||||
- Ubuntu 20.04 Focal
|
||||
- Ubuntu 18.04 Bionic
|
||||
|
||||
`main` branch is the development branch: do not use this for production. Refer to the [release page](https://github.com/AntelopeIO/leap/releases) for current information on releases, pre-releases, and obsolete releases as well as the corresponding tags for those releases.
|
||||
Other Unix derivatives such as macOS are tended to on a best-effort basis and may not be full featured. If you aren't using Ubuntu, please visit the "[Build Unsupported OS](./docs/00_install/01_build-from-source/00_build-unsupported-os.md)" page to explore your options.
|
||||
|
||||
## Software Installation
|
||||
|
||||
Visit the [release page](https://github.com/AntelopeIO/leap/releases) for Ubuntu binaries. This is the fastest way to get started with the software.
|
||||
|
||||
### Building From Source
|
||||
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are:
|
||||
* C++17 compiler and standard library
|
||||
* boost 1.67+
|
||||
* CMake 3.8+
|
||||
* (for Linux only) LLVM 7 - 11 (newer versions do not work)
|
||||
|
||||
A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib.
|
||||
|
||||
**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in Leap are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes.
|
||||
|
||||
Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different Leap versions (Leap requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot).
|
||||
|
||||
#### Building Pinned Build Binary Packages
|
||||
In the directory `<leap src>/scripts` you will find the two scripts `install_deps.sh` and `pinned_build.sh`. If you haven't installed build dependencies then run `install_deps.sh`. Then run `pinned_build.sh <dependencies directory> <leap build directory> <number of jobs>`.
|
||||
|
||||
The dependencies directory is where the script will pull the C++ dependencies that need to be built with the pinned compiler for building the pinned binaries for binary packaging.
|
||||
|
||||
The binary package will be produced in the Leap build directory that was supplied.
|
||||
|
||||
#### Manual (non "pinned") Build Instructions
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 20.04 & 22.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies:
|
||||
If you are running an unsupported Ubuntu derivative, such as Linux Mint, you can find the version of Ubuntu your distribution was based on by using this command:
|
||||
```bash
|
||||
cat /etc/upstream-release/lsb-release
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
pkg-config
|
||||
Your best bet is to follow the instructions for your Ubuntu base, but we make no guarantees.
|
||||
|
||||
## Binary Installation
|
||||
This is the fastest way to get started. From the [latest release](https://github.com/AntelopeIO/leap/releases/latest) page, download a binary for one of our [supported operating systems](#supported-operating-systems), or visit the [release tags](https://github.com/AntelopeIO/leap/releases) page to download a binary for a specific version of Leap.
|
||||
|
||||
Once you have a `*.deb` file downloaded for your version of Ubuntu, you can install it as follows:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ~/Downloads/leap*.deb
|
||||
```
|
||||
and perform the build:
|
||||
Your download path may vary. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default.
|
||||
|
||||
Finally, verify Leap was installed correctly:
|
||||
```bash
|
||||
nodeos --full-version
|
||||
```
|
||||
You should see a [semantic version](https://semver.org) string followed by a `git` commit hash with no errors. For example:
|
||||
```
|
||||
v3.1.2-0b64f879e3ebe2e4df09d2e62f1fc164cc1125d1
|
||||
```
|
||||
|
||||
## Build and Install from Source
|
||||
You can also build and install Leap from source.
|
||||
|
||||
### Prerequisites
|
||||
You will need to build on a [supported operating system](#supported-operating-systems).
|
||||
|
||||
Requirements to build:
|
||||
- C++17 compiler and standard library
|
||||
- boost 1.67+
|
||||
- CMake 3.8+
|
||||
- LLVM 7 - 11 - for Linux only
|
||||
- newer versions do not work
|
||||
- openssl 1.1+
|
||||
- curl
|
||||
- git
|
||||
- GMP
|
||||
- Python 3
|
||||
- zlib
|
||||
|
||||
### Step 1 - Clone
|
||||
If you don't have the Leap repo cloned to your computer yet, [open a terminal](https://itsfoss.com/open-terminal-ubuntu) and navigate to the folder where you want to clone the Leap repository:
|
||||
```bash
|
||||
cd ~/Downloads
|
||||
```
|
||||
Clone Leap using either HTTPS...
|
||||
```bash
|
||||
git clone --recursive https://github.com/AntelopeIO/leap.git
|
||||
```
|
||||
...or SSH:
|
||||
```bash
|
||||
git clone --recursive git@github.com:AntelopeIO/leap.git
|
||||
```
|
||||
|
||||
> ℹ️ **HTTPS vs. SSH Clone** ℹ️
|
||||
Both an HTTPS or SSH git clone will yield the same result - a folder named `leap` containing our source code. It doesn't matter which type you use.
|
||||
|
||||
Navigate into that folder:
|
||||
```bash
|
||||
cd leap
|
||||
```
|
||||
|
||||
### Step 2 - Checkout Release Tag or Branch
|
||||
Choose which [release](https://github.com/AntelopeIO/leap/releases) or [branch](#branches) you would like to build, then check it out. If you are not sure, use the [latest release](https://github.com/AntelopeIO/leap/releases/latest). For example, if you want to build release 3.1.2 then you would check it out using its tag, `v3.1.2`. In the example below, replace `v0.0.0` with your selected release tag accordingly:
|
||||
```bash
|
||||
git fetch --all --tags
|
||||
git checkout v0.0.0
|
||||
```
|
||||
|
||||
Once you are on the branch or release tag you want to build, make sure everything is up-to-date:
|
||||
```bash
|
||||
git pull
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
```
|
||||
|
||||
### Step 3 - Build
|
||||
Select build instructions below for a [pinned build](#pinned-build) (preferred) or an [unpinned build](#unpinned-build).
|
||||
|
||||
> ℹ️ **Pinned vs. Unpinned Build** ℹ️
|
||||
We have two types of builds for Leap: "pinned" and "unpinned." The only difference is that pinned builds use specific versions for some dependencies hand-picked by the Leap engineers - they are "pinned" to those versions. In contrast, unpinned builds use the default dependency versions available on the build system at the time. We recommend performing a "pinned" build to ensure the compiler and boost versions remain the same between builds of different Leap versions. Leap requires these versions to remain the same, otherwise its state might need to be recovered from a portable snapshot or the chain needs to be replayed.
|
||||
|
||||
> ⚠️ **A Warning On Parallel Compilation Jobs (`-j` flag)** ⚠️
|
||||
When building C/C++ software, often the build is performed in parallel via a command such as `make -j "$(nproc)"` which uses all available CPU threads. However, be aware that some compilation units (`*.cpp` files) in Leap will consume nearly 4GB of memory. Failures due to memory exhaustion will typically, but not always, manifest as compiler crashes. Using all available CPU threads may also prevent you from doing other things on your computer during compilation. For these reasons, consider reducing this value.
|
||||
|
||||
> 🐋 **Docker and `sudo`** 🐋
|
||||
If you are in an Ubuntu docker container, omit `sudo` from all commands because you run as `root` by default. Most other docker containers also exclude `sudo`, especially Debian-family containers. If your shell prompt is a hash tag (`#`), omit `sudo`.
|
||||
|
||||
#### Pinned Build
|
||||
Make sure you are in the root of the `leap` repo, then run the `install_depts.sh` script to install dependencies:
|
||||
```bash
|
||||
sudo scripts/install_deps.sh
|
||||
```
|
||||
|
||||
Next, run the pinned build script. You have to give it three arguments, in the following order:
|
||||
- A temporary folder, for all dependencies that need to be built from source.
|
||||
- A build folder, where the binaries you need to install will be built to.
|
||||
- The number of jobs or CPU cores/threads to use (note the [jobs flag](#step-3---build) warning above).
|
||||
|
||||
The following command runs the `pinned_build.sh` script, specifies a `deps` and `build` folder in the root of the Leap repo for the first two arguments, then builds the packages using all of your computer's CPU threads (Note: you don't need `sudo` for this command):
|
||||
```bash
|
||||
scripts/pinned_build.sh deps build "$(nproc)"
|
||||
```
|
||||
Now you can optionally [test](#step-4---test) your build, or [install](#step-5---install) the `*.deb` binary packages, which will be in the root of your build directory.
|
||||
|
||||
#### Unpinned Build
|
||||
The following instructions are valid for this branch. Other release branches may have different requirements, so ensure you follow the directions in the branch or release you intend to build. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default.
|
||||
|
||||
<details> <summary>Ubuntu 22.04 Jammy & Ubuntu 20.04 Focal</summary>
|
||||
|
||||
Install dependencies:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
llvm-11-dev
|
||||
```
|
||||
To build, make sure you are in the root of the `leap` repo, then run the following command:
|
||||
```bash
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 ..
|
||||
make -j $(nproc) package
|
||||
make -j "$(nproc)" package
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 18.04 Build Instructions</summary>
|
||||
<details> <summary>Ubuntu 18.04 Bionic</summary>
|
||||
|
||||
Install required dependencies. You will need to build Boost from source on this distribution.
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
pkg-config \
|
||||
python3 \
|
||||
Install dependencies:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
llvm-7-dev \
|
||||
python3 \
|
||||
zlib1g-dev
|
||||
|
||||
curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \
|
||||
cd boost_1_79_0 && \
|
||||
./bootstrap.sh --prefix=$HOME/boost1.79 && \
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system \
|
||||
--with-program_options --with-chrono --with-test -j$(nproc) install && \
|
||||
cd ..
|
||||
```
|
||||
and perform the build:
|
||||
You need to build Boost from source on this distribution:
|
||||
```bash
|
||||
curl -fL https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 -o ~/Downloads/boost_1_79_0.tar.bz2
|
||||
tar -jvxf ~/Downloads/boost_1_79_0.tar.bz2 -C ~/Downloads/
|
||||
pushd ~/Downloads/boost_1_79_0
|
||||
./bootstrap.sh --prefix="$HOME/boost1.79"
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -j "$(nproc)" install
|
||||
popd
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
The Boost `*.tar.bz2` download and `boost_1_79_0` folder can be removed now if you want more space.
|
||||
```bash
|
||||
rm -r ~/Downloads/boost_1_79_0.tar.bz2 ~/Downloads/boost_1_79_0
|
||||
```
|
||||
From a terminal in the root of the `leap` repo, build.
|
||||
```bash
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release .. \
|
||||
make -j $(nproc) package
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j "$(nproc)" package
|
||||
```
|
||||
After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software.
|
||||
After building, you may remove the `~/boost1.79` directory or you may keep it around for your next build.
|
||||
</details>
|
||||
|
||||
### Running Tests
|
||||
Now you can optionally [test](#step-4---test) your build, or [install](#step-5---install) the `*.deb` binary packages, which will be in the root of your build directory.
|
||||
|
||||
When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel.
|
||||
### Step 4 - Test
|
||||
Leap supports the following test suites:
|
||||
|
||||
```
|
||||
cd build
|
||||
Test Suite | Test Type | [Test Size](https://testing.googleblog.com/2010/12/test-sizes.html) | Notes
|
||||
---|:---:|:---:|---
|
||||
[Parallelizable tests](#parallelizable-tests) | Unit tests | Small
|
||||
[WASM spec tests](#wasm-spec-tests) | Unit tests | Small | Unit tests for our WASM runtime, each short but _very_ CPU-intensive
|
||||
[Serial tests](#serial-tests) | Component/Integration | Medium
|
||||
[Long-running tests](#long-running-tests) | Integration | Medium-to-Large | Tests which take an extraordinarily long amount of time to run
|
||||
|
||||
# "parallelizable tests": the minimum test set that should be run
|
||||
ctest -j $(nproc) -LE _tests
|
||||
When building from source, we recommended running at least the [parallelizable tests](#parallelizable-tests).
|
||||
|
||||
# Also consider running the WASM spec tests for more coverage
|
||||
ctest -j $(nproc) -L wasm_spec_tests
|
||||
#### Parallelizable Tests
|
||||
This test suite consists of any test that does not require shared resources, such as file descriptors, specific folders, or ports, and can therefore be run concurrently in different threads without side effects (hence, easily parallelized). These are mostly unit tests and [small tests](https://testing.googleblog.com/2010/12/test-sizes.html) which complete in a short amount of time.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -j "$(nproc)" -LE _tests
|
||||
```
|
||||
|
||||
Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host.
|
||||
```
|
||||
cd build
|
||||
#### WASM Spec Tests
|
||||
The WASM spec tests verify that our WASM execution engine is compliant with the web assembly standard. These are very [small](https://testing.googleblog.com/2010/12/test-sizes.html), very fast unit tests. However, there are over a thousand of them so the suite can take a little time to run. These tests are extremely CPU-intensive.
|
||||
|
||||
# These tests can't run in parallel but are recommended.
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -j "$(nproc)" -L wasm_spec_tests
|
||||
```
|
||||
We have observed severe performance issues when multiple virtual machines are running this test suite on the same physical host at the same time, for example in a CICD system. This can be resolved by disabling hyperthreading on the host.
|
||||
|
||||
#### Serial Tests
|
||||
The serial test suite consists of [medium](https://testing.googleblog.com/2010/12/test-sizes.html) component or integration tests that use specific paths, ports, rely on process names, or similar, and cannot be run concurrently with other tests. Serial tests can be sensitive to other software running on the same host and they may `SIGKILL` other `nodeos` processes. These tests take a moderate amount of time to complete, but we recommend running them.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -L "nonparallelizable_tests"
|
||||
```
|
||||
|
||||
# These tests can't run in parallel. They also take a long time to run.
|
||||
#### Long-Running Tests
|
||||
The long-running tests are [medium-to-large](https://testing.googleblog.com/2010/12/test-sizes.html) integration tests that rely on shared resources and take a very long time to run.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -L "long_running_tests"
|
||||
```
|
||||
|
||||
### Step 5 - Install
|
||||
Once you have [built](#step-3---build-the-source-code) Leap and [tested](#step-4---test) your build, you can install Leap on your system. Don't forget to omit `sudo` if you are running in a docker container.
|
||||
|
||||
We recommend installing the binary package you just built. Navigate to your Leap build directory in a terminal and run this command:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ./leap[-_][0-9]*.deb
|
||||
```
|
||||
|
||||
It is also possible to install using `make` instead:
|
||||
```bash
|
||||
sudo make install
|
||||
```
|
||||
|
||||
@@ -0,0 +1,686 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
import time
|
||||
import json
|
||||
import signal
|
||||
import rlp
|
||||
import re
|
||||
from ethereum import transactions
|
||||
from binascii import unhexlify
|
||||
|
||||
from TestHarness import Cluster, Node, TestHelper, Utils, WalletMgr
|
||||
from TestHarness.TestHelper import AppArgs
|
||||
from threading import Thread
|
||||
|
||||
###############################################################
|
||||
# nodeos_trust_evm_forked_chain_test
|
||||
#
|
||||
# This test sets up 2 producing nodes and one "bridge" node using test_control_api_plugin.
|
||||
# One producing node has 11 of the elected producers and the other has 10 of the elected producers.
|
||||
# All the producers are named in alphabetical order, so that the 11 producers, in the one production node, are
|
||||
# scheduled first, followed by the 10 producers in the other producer node. Each producing node is only connected
|
||||
# to the other producing node via the "bridge" node.
|
||||
# The bridge node has the test_control_api_plugin, which exposes a restful interface that the test script uses to kill
|
||||
# the "bridge" node at a specific producer in the production cycle. This is used to fork the producer network
|
||||
# precisely when the 11 producer node has finished producing and the other producing node is about to produce.
|
||||
# The fork in the producer network results in one fork of the block chain that advances with 10 producers with a LIB
|
||||
# that has advanced, since all of the previous blocks were confirmed and the producer that was scheduled for that
|
||||
# slot produced it, and one with 11 producers with a LIB that has not advanced. This situation is validated by
|
||||
# the test script.
|
||||
# After both chains are allowed to produce, the "bridge" node is turned back on.
|
||||
# Time is allowed to progress so that the "bridge" node can catchup and both producer nodes to come to consensus
|
||||
# The block log is then checked for both producer nodes to verify that the 10 producer fork is selected and that
|
||||
# both nodes are in agreement on the block log.
|
||||
#
|
||||
###############################################################
|
||||
|
||||
Print=Utils.Print
|
||||
|
||||
from core_symbol import CORE_SYMBOL
|
||||
|
||||
def analyzeBPs(bps0, bps1, expectDivergence):
|
||||
start=0
|
||||
index=None
|
||||
length=len(bps0)
|
||||
firstDivergence=None
|
||||
errorInDivergence=False
|
||||
analysysPass=0
|
||||
bpsStr=None
|
||||
bpsStr0=None
|
||||
bpsStr1=None
|
||||
while start < length:
|
||||
analysysPass+=1
|
||||
bpsStr=None
|
||||
for i in range(start,length):
|
||||
bp0=bps0[i]
|
||||
bp1=bps1[i]
|
||||
if bpsStr is None:
|
||||
bpsStr=""
|
||||
else:
|
||||
bpsStr+=", "
|
||||
blockNum0=bp0["blockNum"]
|
||||
prod0=bp0["prod"]
|
||||
blockNum1=bp1["blockNum"]
|
||||
prod1=bp1["prod"]
|
||||
numDiff=True if blockNum0!=blockNum1 else False
|
||||
prodDiff=True if prod0!=prod1 else False
|
||||
if numDiff or prodDiff:
|
||||
index=i
|
||||
if firstDivergence is None:
|
||||
firstDivergence=min(blockNum0, blockNum1)
|
||||
if not expectDivergence:
|
||||
errorInDivergence=True
|
||||
break
|
||||
bpsStr+=str(blockNum0)+"->"+prod0
|
||||
|
||||
if index is None:
|
||||
if expectDivergence:
|
||||
errorInDivergence=True
|
||||
break
|
||||
return None
|
||||
|
||||
bpsStr0=None
|
||||
bpsStr2=None
|
||||
start=length
|
||||
for i in range(index,length):
|
||||
if bpsStr0 is None:
|
||||
bpsStr0=""
|
||||
bpsStr1=""
|
||||
else:
|
||||
bpsStr0+=", "
|
||||
bpsStr1+=", "
|
||||
bp0=bps0[i]
|
||||
bp1=bps1[i]
|
||||
blockNum0=bp0["blockNum"]
|
||||
prod0=bp0["prod"]
|
||||
blockNum1=bp1["blockNum"]
|
||||
prod1=bp1["prod"]
|
||||
numDiff="*" if blockNum0!=blockNum1 else ""
|
||||
prodDiff="*" if prod0!=prod1 else ""
|
||||
if not numDiff and not prodDiff:
|
||||
start=i
|
||||
index=None
|
||||
if expectDivergence:
|
||||
errorInDivergence=True
|
||||
break
|
||||
bpsStr0+=str(blockNum0)+numDiff+"->"+prod0+prodDiff
|
||||
bpsStr1+=str(blockNum1)+numDiff+"->"+prod1+prodDiff
|
||||
if errorInDivergence:
|
||||
break
|
||||
|
||||
if errorInDivergence:
|
||||
msg="Failed analyzing block producers - "
|
||||
if expectDivergence:
|
||||
msg+="nodes do not indicate different block producers for the same blocks, but they are expected to diverge at some point."
|
||||
else:
|
||||
msg+="did not expect nodes to indicate different block producers for the same blocks."
|
||||
msg+="\n Matching Blocks= %s \n Diverging branch node0= %s \n Diverging branch node1= %s" % (bpsStr,bpsStr0,bpsStr1)
|
||||
Utils.errorExit(msg)
|
||||
|
||||
return firstDivergence
|
||||
|
||||
def getMinHeadAndLib(prodNodes):
|
||||
info0=prodNodes[0].getInfo(exitOnError=True)
|
||||
info1=prodNodes[1].getInfo(exitOnError=True)
|
||||
headBlockNum=min(int(info0["head_block_num"]),int(info1["head_block_num"]))
|
||||
libNum=min(int(info0["last_irreversible_block_num"]), int(info1["last_irreversible_block_num"]))
|
||||
return (headBlockNum, libNum)
|
||||
|
||||
def generate_evm_transactions(nonce, prodNode):
|
||||
while True:
|
||||
Utils.Print("Execute ETH contract")
|
||||
nonce += 1
|
||||
toAdd = "2787b98fc4e731d0456b3941f0b3fe2e01430000"
|
||||
amount = 0
|
||||
unsignedTrx = transactions.Transaction(
|
||||
nonce,
|
||||
150000000000, #150 GWei
|
||||
100000, #100k Gas
|
||||
toAdd,
|
||||
amount,
|
||||
unhexlify("6057361d000000000000000000000000000000000000000000000000000000000000007b")
|
||||
)
|
||||
rlptx = rlp.encode(unsignedTrx.sign(evmSendKey, evmChainId), transactions.Transaction)
|
||||
actData = {"ram_payer":"evmevmevmevm", "rlptx":rlptx.hex()}
|
||||
evmRetValue = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p evmevmevmevm', expiration=300)
|
||||
if not evmRetValue[0]:
|
||||
try:
|
||||
Utils.Print("*** Invalid nonce ***")
|
||||
Utils.Print(f"evmRetValue: {evmRetValue}")
|
||||
found = re.search('"console": "nonce:([0-9]+)', str(evmRetValue[1])).group(1)
|
||||
Utils.Print(f"*** Invalid nonce of {nonce} should be {found} ***")
|
||||
nonce = int(found)
|
||||
nonce -= 1 # for the +1 at top of loop
|
||||
continue
|
||||
except AttributeError as e:
|
||||
Utils.Print(f"Exception {e}")
|
||||
pass
|
||||
assert evmRetValue[0], "pushtx to ETH contract failed."
|
||||
Utils.Print("\tReturn value:", evmRetValue[1]["processed"]["action_traces"][0]["return_value_data"])
|
||||
Utils.Print("\tBlock#", evmRetValue[1]["processed"]["block_num"])
|
||||
row0=prodNode.getTableRow(evmAcc.name, 3, "storage", 0)
|
||||
Utils.Print("\tTable row:", row0)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
appArgs=AppArgs()
|
||||
extraArgs = appArgs.add(flag="--trust-evm-contract-root", type=str, help="TrustEVM contract build dir", default=None)
|
||||
|
||||
args = TestHelper.parse_args({"--prod-count","--dump-error-details","--keep-logs","-v","--leave-running","--clean-run",
|
||||
"--wallet-port"}, applicationSpecificArgs=appArgs)
|
||||
Utils.Debug=args.v
|
||||
totalProducerNodes=2
|
||||
totalNonProducerNodes=1
|
||||
totalNodes=totalProducerNodes+totalNonProducerNodes
|
||||
maxActiveProducers=21
|
||||
totalProducers=maxActiveProducers
|
||||
cluster=Cluster(walletd=True)
|
||||
dumpErrorDetails=args.dump_error_details
|
||||
keepLogs=args.keep_logs
|
||||
dontKill=args.leave_running
|
||||
prodCount=args.prod_count
|
||||
killAll=args.clean_run
|
||||
walletPort=args.wallet_port
|
||||
trustEvmContractRoot=args.trust_evm_contract_root
|
||||
|
||||
walletMgr=WalletMgr(True, port=walletPort)
|
||||
testSuccessful=False
|
||||
killEosInstances=not dontKill
|
||||
killWallet=not dontKill
|
||||
|
||||
WalletdName=Utils.EosWalletName
|
||||
ClientName="cleos"
|
||||
|
||||
assert trustEvmContractRoot is not None, "--trust-evm-contract-root is required"
|
||||
|
||||
try:
|
||||
TestHelper.printSystemInfo("BEGIN")
|
||||
|
||||
cluster.setWalletMgr(walletMgr)
|
||||
cluster.killall(allInstances=killAll)
|
||||
cluster.cleanup()
|
||||
Print("Stand up cluster")
|
||||
specificExtraNodeosArgs={}
|
||||
# producer nodes will be mapped to 0 through totalProducerNodes-1, so the number totalProducerNodes will be the non-producing node
|
||||
specificExtraNodeosArgs[totalProducerNodes]="--plugin eosio::test_control_api_plugin --plugin eosio::state_history_plugin --state-history-endpoint 127.0.0.1:8999 --trace-history --chain-state-history --disable-replay-opts "
|
||||
extraNodeosArgs="--contracts-console"
|
||||
|
||||
|
||||
# *** setup topogrophy ***
|
||||
|
||||
# "bridge" shape connects defprocera through defproducerk (in node0) to each other and defproducerl through defproduceru (in node01)
|
||||
# and the only connection between those 2 groups is through the bridge node
|
||||
|
||||
if cluster.launch(prodCount=prodCount, topo="bridge", pnodes=totalProducerNodes,
|
||||
totalNodes=totalNodes, totalProducers=totalProducers,
|
||||
useBiosBootFile=False, extraNodeosArgs=extraNodeosArgs, specificExtraNodeosArgs=specificExtraNodeosArgs) is False:
|
||||
Utils.cmdError("launcher")
|
||||
Utils.errorExit("Failed to stand up eos cluster.")
|
||||
Print("Validating system accounts after bootstrap")
|
||||
cluster.validateAccounts(None)
|
||||
|
||||
|
||||
# *** create accounts to vote in desired producers ***
|
||||
|
||||
accounts=cluster.createAccountKeys(6)
|
||||
if accounts is None:
|
||||
Utils.errorExit("FAILURE - create keys")
|
||||
accounts[0].name="tester111111"
|
||||
accounts[1].name="tester222222"
|
||||
accounts[2].name="tester333333"
|
||||
accounts[3].name="tester444444"
|
||||
accounts[4].name="tester555555"
|
||||
accounts[5].name="evmevmevmevm"
|
||||
|
||||
evmAcc = accounts[5]
|
||||
|
||||
testWalletName="test"
|
||||
|
||||
Print("Creating wallet \"%s\"." % (testWalletName))
|
||||
testWallet=walletMgr.create(testWalletName, [cluster.eosioAccount,accounts[0],accounts[1],accounts[2],accounts[3],accounts[4],accounts[5]])
|
||||
|
||||
for _, account in cluster.defProducerAccounts.items():
|
||||
walletMgr.importKey(account, testWallet, ignoreDupKeyWarning=True)
|
||||
|
||||
Print("Wallet \"%s\" password=%s." % (testWalletName, testWallet.password.encode("utf-8")))
|
||||
|
||||
|
||||
# *** identify each node (producers and non-producing node) ***
|
||||
|
||||
nonProdNode=None
|
||||
prodNodes=[]
|
||||
producers=[]
|
||||
for i in range(0, totalNodes):
|
||||
node=cluster.getNode(i)
|
||||
node.producers=Cluster.parseProducers(i)
|
||||
numProducers=len(node.producers)
|
||||
Print("node has producers=%s" % (node.producers))
|
||||
if numProducers==0:
|
||||
if nonProdNode is None:
|
||||
nonProdNode=node
|
||||
nonProdNode.nodeNum=i
|
||||
else:
|
||||
Utils.errorExit("More than one non-producing nodes")
|
||||
else:
|
||||
for prod in node.producers:
|
||||
trans=node.regproducer(cluster.defProducerAccounts[prod], "http::/mysite.com", 0, waitForTransBlock=False, exitOnError=True)
|
||||
|
||||
prodNodes.append(node)
|
||||
producers.extend(node.producers)
|
||||
|
||||
|
||||
# *** delegate bandwidth to accounts ***
|
||||
|
||||
node=prodNodes[0]
|
||||
prodNode = node
|
||||
# create accounts via eosio as otherwise a bid is needed
|
||||
for account in accounts:
|
||||
Print("Create new account %s via %s" % (account.name, cluster.eosioAccount.name))
|
||||
trans=node.createInitializeAccount(account, cluster.eosioAccount, stakedDeposit=0, waitForTransBlock=True, stakeNet=10000, stakeCPU=10000, buyRAM=10000000, exitOnError=True)
|
||||
transferAmount="100000000.0000 {0}".format(CORE_SYMBOL)
|
||||
Print("Transfer funds %s from account %s to %s" % (transferAmount, cluster.eosioAccount.name, account.name))
|
||||
node.transferFunds(cluster.eosioAccount, account, transferAmount, "test transfer", waitForTransBlock=True)
|
||||
trans=node.delegatebw(account, 20000000.0000, 20000000.0000, waitForTransBlock=True, exitOnError=True)
|
||||
|
||||
|
||||
# *** vote using accounts ***
|
||||
|
||||
#verify nodes are in sync and advancing
|
||||
cluster.waitOnClusterSync(blockAdvancing=5)
|
||||
index=0
|
||||
for account in accounts:
|
||||
Print("Vote for producers=%s" % (producers))
|
||||
trans=prodNodes[index % len(prodNodes)].vote(account, producers, waitForTransBlock=True)
|
||||
index+=1
|
||||
|
||||
# *** Setup EVM contract ***
|
||||
|
||||
contractDir=trustEvmContractRoot + "/evm_runtime"
|
||||
wasmFile="evm_runtime.wasm"
|
||||
abiFile="evm_runtime.abi"
|
||||
Utils.Print("Publish evm_runtime contract")
|
||||
evmTrans = prodNode.publishContract(evmAcc, contractDir, wasmFile, abiFile, waitForTransBlock=True)
|
||||
transId=prodNode.getTransId(evmTrans)
|
||||
blockNum = prodNode.getBlockNumByTransId(transId)
|
||||
block = prodNode.getBlock(blockNum)
|
||||
Utils.Print("Block Id: ", block["id"])
|
||||
Utils.Print("Block timestamp: ", block["timestamp"])
|
||||
|
||||
Utils.Print("Set balance")
|
||||
evmTrans = prodNode.pushMessage(evmAcc.name, "setbal", '{"addy":"2787b98fc4e731d0456b3941f0b3fe2e01439961", "bal":"0000000000000000000000000000000100000000000000000000000000000000"}', '-p evmevmevmevm')
|
||||
prodNode.waitForTransBlockIfNeeded(evmTrans[1], True)
|
||||
|
||||
Utils.Print("Send balance")
|
||||
evmChainId = 15555
|
||||
fromAdd = "2787b98fc4e731d0456b3941f0b3fe2e01439961"
|
||||
toAdd = '0x9edf022004846bc987799d552d1b8485b317b7ed'
|
||||
amount = 100
|
||||
nonce = 0
|
||||
evmSendKey = "a3f1b69da92a0233ce29485d3049a4ace39e8d384bbc2557e3fc60940ce4e954"
|
||||
unsignedTrx = transactions.Transaction(
|
||||
nonce,
|
||||
150000000000, #150 GWei
|
||||
100000, #100k Gas
|
||||
toAdd,
|
||||
amount,
|
||||
b''
|
||||
)
|
||||
rlptx = rlp.encode(unsignedTrx.sign(evmSendKey, evmChainId), transactions.Transaction)
|
||||
actData = {"ram_payer":"evmevmevmevm", "rlptx":rlptx.hex()}
|
||||
evmTrans = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p evmevmevmevm')
|
||||
prodNode.waitForTransBlockIfNeeded(evmTrans[1], True)
|
||||
|
||||
Utils.Print("Send balance again, should fail with wrong nonce")
|
||||
retValue = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p evmevmevmevm', silentErrors=True, force=True)
|
||||
assert not retValue[0], f"push trx should have failed: {retValue}"
|
||||
|
||||
Utils.Print("Simple Solidity contract")
|
||||
# // SPDX-License-Identifier: GPL-3.0
|
||||
# pragma solidity >=0.7.0 <0.9.0;
|
||||
# contract Storage {
|
||||
# uint256 number;
|
||||
# function store(uint256 num) public {
|
||||
# number = num;
|
||||
# }
|
||||
# function retrieve() public view returns (uint256){
|
||||
# return number;
|
||||
# }
|
||||
# }
|
||||
retValue = prodNode.pushMessage(evmAcc.name, "updatecode", '{"address":"2787b98fc4e731d0456b3941f0b3fe2e01430000","incarnation":0,"code_hash":"286e3d498e2178afc91275f11d446e62a0d85b060ce66d6ca75f6ec9d874d560","code":"608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212209a159a4f3847890f10bfb87871a61eba91c5dbf5ee3cf6398207e292eee22a1664736f6c63430008070033"}', '-p evmevmevmevm')
|
||||
|
||||
Utils.Print("Pausing for setup of trustevm node")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
# start generating evm transactions
|
||||
thread = Thread(target=generate_evm_transactions, args=(nonce, prodNode))
|
||||
thread.start()
|
||||
|
||||
Print("Thread spawned")
|
||||
|
||||
# *** Identify a block where production is stable ***
|
||||
|
||||
#verify nodes are in sync and advancing
|
||||
cluster.waitOnClusterSync(blockAdvancing=5)
|
||||
blockNum=node.getNextCleanProductionCycle(trans)
|
||||
blockProducer=node.getBlockProducerByNum(blockNum)
|
||||
Print("Validating blockNum=%s, producer=%s" % (blockNum, blockProducer))
|
||||
cluster.biosNode.kill(signal.SIGTERM)
|
||||
|
||||
class HeadWaiter:
|
||||
def __init__(self, node):
|
||||
self.node=node
|
||||
self.cachedHeadBlockNum=node.getBlockNum()
|
||||
|
||||
def waitIfNeeded(self, blockNum):
|
||||
delta=self.cachedHeadBlockNum-blockNum
|
||||
if delta >= 0:
|
||||
return
|
||||
previousHeadBlockNum=self.cachedHeadBlockNum
|
||||
delta=-1*delta
|
||||
timeout=(delta+1)/2 + 3 # round up to nearest second and 3 second extra leeway
|
||||
self.node.waitForBlock(blockNum, timeout=timeout)
|
||||
self.cachedHeadBlockNum=node.getBlockNum()
|
||||
if blockNum > self.cachedHeadBlockNum:
|
||||
Utils.errorExit("Failed to advance from block number %d to %d in %d seconds. Only got to block number %d" % (previousHeadBlockNum, blockNum, timeout, self.cachedHeadBlockNum))
|
||||
|
||||
def getBlock(self, blockNum):
|
||||
self.waitIfNeeded(blockNum)
|
||||
return self.node.getBlock(blockNum)
|
||||
|
||||
#advance to the next block of 12
|
||||
lastBlockProducer=blockProducer
|
||||
|
||||
waiter=HeadWaiter(node)
|
||||
|
||||
while blockProducer==lastBlockProducer:
|
||||
blockNum+=1
|
||||
block=waiter.getBlock(blockNum)
|
||||
Utils.Print("Block num: %d, block: %s" % (blockNum, json.dumps(block, indent=4, sort_keys=True)))
|
||||
blockProducer=Node.getBlockAttribute(block, "producer", blockNum)
|
||||
|
||||
timestampStr=Node.getBlockAttribute(block, "timestamp", blockNum)
|
||||
timestamp=datetime.strptime(timestampStr, Utils.TimeFmt)
|
||||
|
||||
|
||||
# *** Identify what the production cycle is ***
|
||||
|
||||
productionCycle=[]
|
||||
producerToSlot={}
|
||||
slot=-1
|
||||
inRowCountPerProducer=12
|
||||
minNumBlocksPerProducer=10
|
||||
lastTimestamp=timestamp
|
||||
headBlockNum=node.getBlockNum()
|
||||
firstBlockForWindowMissedSlot=None
|
||||
while True:
|
||||
if blockProducer not in producers:
|
||||
Utils.errorExit("Producer %s was not one of the voted on producers" % blockProducer)
|
||||
|
||||
productionCycle.append(blockProducer)
|
||||
slot+=1
|
||||
if blockProducer in producerToSlot:
|
||||
Utils.errorExit("Producer %s was first seen in slot %d, but is repeated in slot %d" % (blockProducer, producerToSlot[blockProducer], slot))
|
||||
|
||||
producerToSlot[blockProducer]={"slot":slot, "count":0}
|
||||
lastBlockProducer=blockProducer
|
||||
blockSkip=[]
|
||||
roundSkips=0
|
||||
missedSlotAfter=[]
|
||||
if firstBlockForWindowMissedSlot is not None:
|
||||
missedSlotAfter.append(firstBlockForWindowMissedSlot)
|
||||
firstBlockForWindowMissedSlot=None
|
||||
|
||||
while blockProducer==lastBlockProducer:
|
||||
producerToSlot[blockProducer]["count"]+=1
|
||||
blockNum+=1
|
||||
block=waiter.getBlock(blockNum)
|
||||
blockProducer=Node.getBlockAttribute(block, "producer", blockNum)
|
||||
timestampStr=Node.getBlockAttribute(block, "timestamp", blockNum)
|
||||
timestamp=datetime.strptime(timestampStr, Utils.TimeFmt)
|
||||
timediff=timestamp-lastTimestamp
|
||||
slotTime=0.5
|
||||
slotsDiff=int(timediff.total_seconds() / slotTime)
|
||||
if slotsDiff != 1:
|
||||
slotTimeDelta=timedelta(slotTime)
|
||||
first=lastTimestamp + slotTimeDelta
|
||||
missed=first.strftime(Utils.TimeFmt)
|
||||
if slotsDiff > 2:
|
||||
last=timestamp - slotTimeDelta
|
||||
missed+= " thru " + last.strftime(Utils.TimeFmt)
|
||||
missedSlotAfter.append("%d (%s)" % (blockNum-1, missed))
|
||||
lastTimestamp=timestamp
|
||||
|
||||
if producerToSlot[lastBlockProducer]["count"] < minNumBlocksPerProducer or producerToSlot[lastBlockProducer]["count"] > inRowCountPerProducer:
|
||||
Utils.errorExit("Producer %s, in slot %d, expected to produce %d blocks but produced %d blocks. At block number %d. " %
|
||||
(lastBlockProducer, slot, inRowCountPerProducer, producerToSlot[lastBlockProducer]["count"], blockNum-1) +
|
||||
"Slots were missed after the following blocks: %s" % (", ".join(missedSlotAfter)))
|
||||
|
||||
if len(missedSlotAfter) > 0:
|
||||
# it may be the most recent producer missed a slot
|
||||
possibleMissed=missedSlotAfter[-1]
|
||||
if possibleMissed == blockNum - 1:
|
||||
firstBlockForWindowMissedSlot=possibleMissed
|
||||
|
||||
if blockProducer==productionCycle[0]:
|
||||
break
|
||||
|
||||
output=None
|
||||
for blockProducer in productionCycle:
|
||||
if output is None:
|
||||
output=""
|
||||
else:
|
||||
output+=", "
|
||||
output+=blockProducer+":"+str(producerToSlot[blockProducer]["count"])
|
||||
Print("ProductionCycle ->> {\n%s\n}" % output)
|
||||
|
||||
#retrieve the info for all the nodes to report the status for each
|
||||
for node in cluster.getNodes():
|
||||
node.getInfo()
|
||||
cluster.reportStatus()
|
||||
|
||||
|
||||
# *** Killing the "bridge" node ***
|
||||
|
||||
Print("Sending command to kill \"bridge\" node to separate the 2 producer groups.")
|
||||
# block number to start expecting node killed after
|
||||
preKillBlockNum=nonProdNode.getBlockNum()
|
||||
preKillBlockProducer=nonProdNode.getBlockProducerByNum(preKillBlockNum)
|
||||
Print("preKillBlockProducer = {}".format(preKillBlockProducer))
|
||||
# kill at last block before defproducerl, since the block it is killed on will get propagated
|
||||
killAtProducer="defproducerk"
|
||||
nonProdNode.killNodeOnProducer(producer=killAtProducer, whereInSequence=(inRowCountPerProducer-1))
|
||||
|
||||
|
||||
# *** Identify a highest block number to check while we are trying to identify where the divergence will occur ***
|
||||
|
||||
# will search full cycle after the current block, since we don't know how many blocks were produced since retrieving
|
||||
# block number and issuing kill command
|
||||
postKillBlockNum=prodNodes[1].getBlockNum()
|
||||
blockProducers0=[]
|
||||
blockProducers1=[]
|
||||
libs0=[]
|
||||
libs1=[]
|
||||
lastBlockNum=max([preKillBlockNum,postKillBlockNum])+2*maxActiveProducers*inRowCountPerProducer
|
||||
actualLastBlockNum=None
|
||||
prodChanged=False
|
||||
nextProdChange=False
|
||||
#identify the earliest LIB to start identify the earliest block to check if divergent branches eventually reach concensus
|
||||
(headBlockNum, libNumAroundDivergence)=getMinHeadAndLib(prodNodes)
|
||||
Print("Tracking block producers from %d till divergence or %d. Head block is %d and lowest LIB is %d" % (preKillBlockNum, lastBlockNum, headBlockNum, libNumAroundDivergence))
|
||||
transitionCount=0
|
||||
missedTransitionBlock=None
|
||||
for blockNum in range(preKillBlockNum,lastBlockNum + 1):
|
||||
#avoiding getting LIB until my current block passes the head from the last time I checked
|
||||
if blockNum>headBlockNum:
|
||||
(headBlockNum, libNumAroundDivergence)=getMinHeadAndLib(prodNodes)
|
||||
|
||||
# track the block number and producer from each producing node
|
||||
# we use timeout 70 here because of case when chain break, call to getBlockProducerByNum
|
||||
# and call of producer_plugin::schedule_delayed_production_loop happens nearly immediately
|
||||
# for 10 producers wait cycle is 10 * (12*0.5) = 60 seconds.
|
||||
# for 11 producers wait cycle is 11 * (12*0.5) = 66 seconds.
|
||||
blockProducer0=prodNodes[0].getBlockProducerByNum(blockNum, timeout=70)
|
||||
blockProducer1=prodNodes[1].getBlockProducerByNum(blockNum, timeout=70)
|
||||
Print("blockNum = {} blockProducer0 = {} blockProducer1 = {}".format(blockNum, blockProducer0, blockProducer1))
|
||||
blockProducers0.append({"blockNum":blockNum, "prod":blockProducer0})
|
||||
blockProducers1.append({"blockNum":blockNum, "prod":blockProducer1})
|
||||
|
||||
#in the case that the preKillBlockNum was also produced by killAtProducer, ensure that we have
|
||||
#at least one producer transition before checking for killAtProducer
|
||||
if not prodChanged:
|
||||
if preKillBlockProducer!=blockProducer0:
|
||||
prodChanged=True
|
||||
Print("prodChanged = True")
|
||||
|
||||
#since it is killing for the last block of killAtProducer, we look for the next producer change
|
||||
if not nextProdChange and prodChanged and blockProducer1==killAtProducer:
|
||||
nextProdChange=True
|
||||
Print("nextProdChange = True")
|
||||
elif nextProdChange and blockProducer1!=killAtProducer:
|
||||
Print("nextProdChange = False")
|
||||
if blockProducer0!=blockProducer1:
|
||||
Print("Divergence identified at block %s, node_00 producer: %s, node_01 producer: %s" % (blockNum, blockProducer0, blockProducer1))
|
||||
actualLastBlockNum=blockNum
|
||||
break
|
||||
else:
|
||||
missedTransitionBlock=blockNum
|
||||
transitionCount+=1
|
||||
Print("missedTransitionBlock = {} transitionCount = {}".format(missedTransitionBlock, transitionCount))
|
||||
# allow this to transition twice, in case the script was identifying an earlier transition than the bridge node received the kill command
|
||||
if transitionCount>1:
|
||||
Print("At block %d and have passed producer: %s %d times and we have not diverged, stopping looking and letting errors report" % (blockNum, killAtProducer, transitionCount))
|
||||
actualLastBlockNum=blockNum
|
||||
break
|
||||
|
||||
#if we diverge before identifying the actualLastBlockNum, then there is an ERROR
|
||||
if blockProducer0!=blockProducer1:
|
||||
extra="" if transitionCount==0 else " Diverged after expected killAtProducer transition at block %d." % (missedTransitionBlock)
|
||||
Utils.errorExit("Groups reported different block producers for block number %d.%s %s != %s." % (blockNum,extra,blockProducer0,blockProducer1))
|
||||
|
||||
#verify that the non producing node is not alive (and populate the producer nodes with current getInfo data to report if
|
||||
#an error occurs)
|
||||
if nonProdNode.verifyAlive():
|
||||
Utils.errorExit("Expected the non-producing node to have shutdown.")
|
||||
|
||||
Print("Analyzing the producers leading up to the block after killing the non-producing node, expecting divergence at %d" % (blockNum))
|
||||
|
||||
firstDivergence=analyzeBPs(blockProducers0, blockProducers1, expectDivergence=True)
|
||||
# Nodes should not have diverged till the last block
|
||||
if firstDivergence!=blockNum:
|
||||
Utils.errorExit("Expected to diverge at %s, but diverged at %s." % (firstDivergence, blockNum))
|
||||
blockProducers0=[]
|
||||
blockProducers1=[]
|
||||
|
||||
for prodNode in prodNodes:
|
||||
info=prodNode.getInfo()
|
||||
Print("node info: %s" % (info))
|
||||
|
||||
killBlockNum=blockNum
|
||||
lastBlockNum=killBlockNum+(maxActiveProducers - 1)*inRowCountPerProducer+1 # allow 1st testnet group to produce just 1 more block than the 2nd
|
||||
|
||||
Print("Tracking the blocks from the divergence till there are 10*12 blocks on one chain and 10*12+1 on the other, from block %d to %d" % (killBlockNum, lastBlockNum))
|
||||
|
||||
for blockNum in range(killBlockNum,lastBlockNum):
|
||||
blockProducer0=prodNodes[0].getBlockProducerByNum(blockNum)
|
||||
blockProducer1=prodNodes[1].getBlockProducerByNum(blockNum)
|
||||
blockProducers0.append({"blockNum":blockNum, "prod":blockProducer0})
|
||||
blockProducers1.append({"blockNum":blockNum, "prod":blockProducer1})
|
||||
|
||||
|
||||
Print("Analyzing the producers from the divergence to the lastBlockNum and verify they stay diverged, expecting divergence at block %d" % (killBlockNum))
|
||||
|
||||
firstDivergence=analyzeBPs(blockProducers0, blockProducers1, expectDivergence=True)
|
||||
if firstDivergence!=killBlockNum:
|
||||
Utils.errorExit("Expected to diverge at %s, but diverged at %s." % (firstDivergence, killBlockNum))
|
||||
blockProducers0=[]
|
||||
blockProducers1=[]
|
||||
|
||||
for prodNode in prodNodes:
|
||||
info=prodNode.getInfo()
|
||||
Print("node info: %s" % (info))
|
||||
|
||||
Print("Relaunching the non-producing bridge node to connect the producing nodes again")
|
||||
|
||||
if not nonProdNode.relaunch():
|
||||
Utils.errorExit("Failure - (non-production) node %d should have restarted" % (nonProdNode.nodeNum))
|
||||
|
||||
|
||||
Print("Waiting to allow forks to resolve")
|
||||
|
||||
for prodNode in prodNodes:
|
||||
info=prodNode.getInfo()
|
||||
Print("node info: %s" % (info))
|
||||
|
||||
#ensure that the nodes have enough time to get in concensus, so wait for 3 producers to produce their complete round
|
||||
time.sleep(inRowCountPerProducer * 3 / 2)
|
||||
remainingChecks=60
|
||||
match=False
|
||||
checkHead=False
|
||||
checkMatchBlock=killBlockNum
|
||||
forkResolved=False
|
||||
while remainingChecks>0:
|
||||
if checkMatchBlock == killBlockNum and checkHead:
|
||||
checkMatchBlock = prodNodes[0].getBlockNum()
|
||||
blockProducer0=prodNodes[0].getBlockProducerByNum(checkMatchBlock)
|
||||
blockProducer1=prodNodes[1].getBlockProducerByNum(checkMatchBlock)
|
||||
match=blockProducer0==blockProducer1
|
||||
if match:
|
||||
if checkHead:
|
||||
forkResolved=True
|
||||
break
|
||||
else:
|
||||
checkHead=True
|
||||
continue
|
||||
Print("Fork has not resolved yet, wait a little more. Block %s has producer %s for node_00 and %s for node_01. Original divergence was at block %s. Wait time remaining: %d" % (checkMatchBlock, blockProducer0, blockProducer1, killBlockNum, remainingChecks))
|
||||
time.sleep(1)
|
||||
remainingChecks-=1
|
||||
|
||||
assert forkResolved, "fork was not resolved in a reasonable time. node_00 lib {} head {} node_01 lib {} head {}".format(
|
||||
prodNodes[0].getIrreversibleBlockNum(),
|
||||
prodNodes[0].getHeadBlockNum(),
|
||||
prodNodes[1].getIrreversibleBlockNum(),
|
||||
prodNodes[1].getHeadBlockNum())
|
||||
|
||||
for prodNode in prodNodes:
|
||||
info=prodNode.getInfo()
|
||||
Print("node info: %s" % (info))
|
||||
|
||||
# ensure all blocks from the lib before divergence till the current head are now in consensus
|
||||
endBlockNum=max(prodNodes[0].getBlockNum(), prodNodes[1].getBlockNum())
|
||||
|
||||
Print("Identifying the producers from the saved LIB to the current highest head, from block %d to %d" % (libNumAroundDivergence, endBlockNum))
|
||||
|
||||
for blockNum in range(libNumAroundDivergence,endBlockNum):
|
||||
blockProducer0=prodNodes[0].getBlockProducerByNum(blockNum)
|
||||
blockProducer1=prodNodes[1].getBlockProducerByNum(blockNum)
|
||||
blockProducers0.append({"blockNum":blockNum, "prod":blockProducer0})
|
||||
blockProducers1.append({"blockNum":blockNum, "prod":blockProducer1})
|
||||
|
||||
|
||||
Print("Analyzing the producers from the saved LIB to the current highest head and verify they match now")
|
||||
|
||||
analyzeBPs(blockProducers0, blockProducers1, expectDivergence=False)
|
||||
|
||||
resolvedKillBlockProducer=None
|
||||
for prod in blockProducers0:
|
||||
if prod["blockNum"]==killBlockNum:
|
||||
resolvedKillBlockProducer = prod["prod"]
|
||||
if resolvedKillBlockProducer is None:
|
||||
Utils.errorExit("Did not find find block %s (the original divergent block) in blockProducers0, test setup is wrong. blockProducers0: %s" % (killBlockNum, ", ".join(blockProducers0)))
|
||||
Print("Fork resolved and determined producer %s for block %s" % (resolvedKillBlockProducer, killBlockNum))
|
||||
|
||||
blockProducers0=[]
|
||||
blockProducers1=[]
|
||||
|
||||
Utils.Print("Press enter to end test")
|
||||
input("Press Enter...")
|
||||
|
||||
|
||||
testSuccessful=True
|
||||
finally:
|
||||
TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, killEosInstances=killEosInstances, killWallet=killWallet, keepLogs=keepLogs, cleanRun=killAll, dumpErrorDetails=dumpErrorDetails)
|
||||
|
||||
exitCode = 0 if testSuccessful else 1
|
||||
exit(exitCode)
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
"name": "eos",
|
||||
"generators": [
|
||||
{
|
||||
"name": "collate_markdown",
|
||||
"options": {
|
||||
"docs_dir": "docs"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/chain_api_plugin/chain.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/chain_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/db_size_api_plugin/db_size.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/db_size_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/producer_api_plugin/producer.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/producer_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/net_api_plugin/net.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/net_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/test_control_api_plugin/test_control.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/test_control_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/trace_api_plugin/trace_api.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/trace_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,123 +2,19 @@
|
||||
content_title: Build Antelope from Source
|
||||
---
|
||||
|
||||
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests.
|
||||
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the [`README.md`](https://github.com/AntelopeIO/leap/blob/main/README.md) file. Instructions are also included for efficiently running the tests.
|
||||
|
||||
### Using DUNE
|
||||
|
||||
As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support.
|
||||
As an alternative to building from source, try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started and for multi-platform support.
|
||||
|
||||
### Building From Source
|
||||
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are:
|
||||
* C++17 compiler and standard library
|
||||
* boost 1.67+
|
||||
* CMake 3.8+
|
||||
* (for Linux only) LLVM 7 - 11 (newer versions do not work)
|
||||
|
||||
A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib.
|
||||
|
||||
**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes.
|
||||
|
||||
Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different mandel versions (mandel requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot).
|
||||
You can also build and install Leap from source. Instructions for that currently live [here](https://github.com/AntelopeIO/leap/blob/main/README.md#build-and-install-from-source).
|
||||
|
||||
#### Building Pinned Build Binary Packages
|
||||
In the directory `<mandel src>/scripts` you will find the two scripts `install_deps.sh` and `pinned_build.sh`. If you haven't installed build dependencies then run `install_deps.sh`. Then run `pinned_build.sh <dependencies directory> <mandel build directory> <number of jobs>`.
|
||||
|
||||
The dependencies directory is where the script will pull the C++ dependencies that need to be built with the pinned compiler for building the pinned binaries for binary packaging.
|
||||
|
||||
The binary package will be produced in the mandel build directory that was supplied.
|
||||
The pinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#pinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/main/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/main/README.md#step-3---build) before you build.
|
||||
|
||||
#### Manual (non "pinned") Build Instructions
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 20.04 & 22.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies:
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
pkg-config
|
||||
```
|
||||
and perform the build:
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j $(nproc) package
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 18.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies. You will need to build Boost from source on this distribution.
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
pkg-config \
|
||||
python3 \
|
||||
zlib1g-dev
|
||||
|
||||
curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \
|
||||
cd boost_1_79_0 && \
|
||||
./bootstrap.sh --prefix=$HOME/boost1.79 && \
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system \
|
||||
--with-program_options --with-chrono --with-test -j$(nproc) install && \
|
||||
cd ..
|
||||
```
|
||||
and perform the build:
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release .. \
|
||||
make -j $(nproc) package
|
||||
```
|
||||
After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software.
|
||||
</details>
|
||||
The unpinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#unpinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/main/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/main/README.md#step-3---build) before you build.
|
||||
|
||||
### Running Tests
|
||||
|
||||
When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel.
|
||||
|
||||
```
|
||||
cd build
|
||||
|
||||
# "parallelizable tests": the minimum test set that should be run
|
||||
ctest -j $(nproc) -LE _tests
|
||||
|
||||
# Also consider running the WASM spec tests for more coverage
|
||||
ctest -j $(nproc) -L wasm_spec_tests
|
||||
```
|
||||
|
||||
Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host.
|
||||
```
|
||||
cd build
|
||||
|
||||
# These tests can't run in parallel but are recommended.
|
||||
ctest -L "nonparallelizable_tests"
|
||||
|
||||
# These tests can't run in parallel. They also take a long time to run.
|
||||
ctest -L "long_running_tests"
|
||||
```
|
||||
Documentation on available test suites and how to run them has moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#test).
|
||||
|
||||
@@ -10,9 +10,9 @@ The best way to install and use the Antelope software is to build it from source
|
||||
|
||||
Antelope currently supports the following operating systems:
|
||||
|
||||
1. Ubuntu 18.04
|
||||
2. Ubuntu 20.04
|
||||
3. Ubuntu 22.04
|
||||
1. Ubuntu 22.04 Jammy
|
||||
2. Ubuntu 20.04 Focal
|
||||
3. Ubuntu 18.04 Bionic
|
||||
|
||||
[[info | Note]]
|
||||
| It may be possible to build and install Antelope on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported.
|
||||
|
||||
@@ -114,35 +114,18 @@ Config Options for eosio::chain_plugin:
|
||||
subjective whitelist/blacklist checks
|
||||
applied to them (may specify multiple
|
||||
times)
|
||||
--read-mode arg (=speculative) Database read mode ("speculative",
|
||||
"head", "read-only", "irreversible").
|
||||
In "speculative" mode: database
|
||||
contains state changes by transactions
|
||||
in the blockchain up to the head block
|
||||
as well as some transactions not yet
|
||||
included in the blockchain.
|
||||
--read-mode arg (=head) Database read mode ("head",
|
||||
"irreversible").
|
||||
In "head" mode: database contains state
|
||||
changes by only transactions in the
|
||||
blockchain up to the head block;
|
||||
transactions received by the node are
|
||||
changes up to the head block;
|
||||
transactions received by the node are
|
||||
relayed if valid.
|
||||
In "read-only" mode: (DEPRECATED: see
|
||||
p2p-accept-transactions &
|
||||
api-accept-transactions) database
|
||||
contains state changes by only
|
||||
transactions in the blockchain up to
|
||||
the head block; transactions received
|
||||
via the P2P network are not relayed and
|
||||
transactions cannot be pushed via the
|
||||
chain API.
|
||||
In "irreversible" mode: database
|
||||
contains state changes by only
|
||||
transactions in the blockchain up to
|
||||
the last irreversible block;
|
||||
transactions received via the P2P
|
||||
network are not relayed and
|
||||
transactions cannot be pushed via the
|
||||
chain API.
|
||||
In "irreversible" mode: database
|
||||
contains state changes up to the last
|
||||
irreversible block; transactions
|
||||
received via the P2P network are not
|
||||
relayed and transactions cannot be
|
||||
pushed via the chain API.
|
||||
|
||||
--api-accept-transactions arg (=1) Allow API transactions to be evaluated
|
||||
and relayed if valid.
|
||||
|
||||
@@ -13,7 +13,6 @@ For information on specific plugins, just select from the list below:
|
||||
* [`db_size_api_plugin`](db_size_api_plugin/index.md)
|
||||
* [`http_client_plugin`](http_client_plugin/index.md)
|
||||
* [`http_plugin`](http_plugin/index.md)
|
||||
* [`login_plugin`](login_plugin/index.md)
|
||||
* [`net_api_plugin`](net_api_plugin/index.md)
|
||||
* [`net_plugin`](net_plugin/index.md)
|
||||
* [`producer_plugin`](producer_plugin/index.md)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
## Description
|
||||
|
||||
The `login_plugin` supports the concept of applications authenticating with the Antelope blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority.
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
# config.ini
|
||||
plugin = eosio::login_plugin
|
||||
[options]
|
||||
```
|
||||
```sh
|
||||
# command-line
|
||||
nodeos ... --plugin eosio::login_plugin [options]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
These can be specified from both the `nodeos` command-line or the `config.ini` file:
|
||||
|
||||
```console
|
||||
Config Options for eosio::login_plugin:
|
||||
--max-login-requests arg (=1000000) The maximum number of pending login
|
||||
requests
|
||||
--max-login-timeout arg (=60) The maximum timeout for pending login
|
||||
requests (in seconds)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [`chain_plugin`](../chain_plugin/index.md)
|
||||
* [`http_plugin`](../http_plugin/index.md)
|
||||
|
||||
### Load Dependency Examples
|
||||
|
||||
```console
|
||||
# config.ini
|
||||
plugin = eosio::chain_plugin
|
||||
[options]
|
||||
plugin = eosio::http_plugin
|
||||
[options]
|
||||
```
|
||||
```sh
|
||||
# command-line
|
||||
nodeos ... --plugin eosio::chain_plugin [options] \
|
||||
--plugin eosio::http_plugin [options]
|
||||
```
|
||||
@@ -135,8 +135,6 @@ Config Options for eosio::producer_plugin:
|
||||
transaction queue. Exceeding this value
|
||||
will subjectively drop transaction with
|
||||
resource exhaustion.
|
||||
--disable-api-persisted-trx Disable the re-apply of API
|
||||
transactions.
|
||||
--disable-subjective-billing arg (=1) Disable subjective CPU billing for
|
||||
API/P2P transactions
|
||||
--disable-subjective-account-billing arg
|
||||
|
||||
@@ -27,38 +27,17 @@ The `nodeos` service provides query access to the chain database via the HTTP [R
|
||||
|
||||
The `nodeos` service can be run in different "read" modes. These modes control how the node operates and how it processes blocks and transactions:
|
||||
|
||||
- `speculative`: this includes the side effects of confirmed and unconfirmed transactions.
|
||||
- `head`: this only includes the side effects of confirmed transactions, this mode processes unconfirmed transactions but does not include them.
|
||||
- `read-only`: this mode is deprecated. Similar functionality can be achieved by combining options: `read-mode = head`, `p2p-accept-transactions = false`, `api-accept-transactions = false`. When these options are set, the local database will contain state changes made by transactions in the chain up to the head block. Also, transactions received via the P2P network are not relayed and transactions cannot be pushed via the chain API.
|
||||
- `irreversible`: this mode also includes confirmed transactions only up to those included in the last irreversible block.
|
||||
|
||||
A transaction is considered confirmed when a `nodeos` instance has received, processed, and written it to a block on the blockchain, i.e. it is in the head block or an earlier block.
|
||||
|
||||
### Speculative Mode
|
||||
|
||||
Clients such as `cleos` and the RPC API, will see database state as of the current head block plus changes made by all transactions known to this node but potentially not included in the chain, unconfirmed transactions for example.
|
||||
|
||||
Speculative mode is low latency but fragile, there is no guarantee that the transactions reflected in the state will be included in the chain OR that they will reflected in the same order the state implies.
|
||||
|
||||
This mode features the lowest latency, but is the least consistent.
|
||||
|
||||
In speculative mode `nodeos` is able to execute transactions which have TaPoS (Transaction as Proof of Stake) pointing to any valid block in a fork considered to be the best fork by this node.
|
||||
|
||||
### Head Mode
|
||||
|
||||
Clients such as `cleos` and the RPC API will see database state as of the current head block of the chain. Since current head block is not yet irreversible and short-lived forks are possible, state read in this mode may become inaccurate if `nodeos` switches to a better fork. Note that this is also true of speculative mode.
|
||||
|
||||
This mode represents a good trade-off between highly consistent views of the data and latency.
|
||||
Clients such as `cleos` and the RPC API will see database state as of the current head block of the chain. Since current head block is not yet irreversible and short-lived forks are possible, state read in this mode may become inaccurate if `nodeos` switches to a better fork.
|
||||
|
||||
In this mode `nodeos` is able to execute transactions which have TaPoS pointing to any valid block in a fork considered to be the best fork by this node.
|
||||
|
||||
### Read-Only Mode
|
||||
|
||||
[[caution | Deprecation Notice]]
|
||||
| The explicit `read-mode = read-only` mode is deprecated. Similar functionality can now be achieved in `head` mode by combining options: `read-mode = head`, `p2p-accept-transactions = false`, `api-accept-transactions = false`.
|
||||
|
||||
Clients such as `cleos` and the RPC API will see database state as of the current head block of the chain. It **will not** include changes made by transactions known to this node but not included in the chain, such as unconfirmed transactions.
|
||||
|
||||
### Irreversible Mode
|
||||
|
||||
When `nodeos` is configured to be in irreversible read mode, it will still track the most up-to-date blocks in the fork database, but the state will lag behind the current best head block, sometimes referred to as the fork DB head, to always reflect the state of the last irreversible block.
|
||||
|
||||
@@ -91,11 +91,6 @@ Config Options for eosio::wallet_plugin:
|
||||
number of seconds of inactivity.
|
||||
Activity is defined as any wallet
|
||||
command e.g. list-wallets.
|
||||
--yubihsm-url URL Override default URL of
|
||||
http://localhost:12345 for connecting
|
||||
to yubihsm-connector
|
||||
--yubihsm-authkey key_num Enables YubiHSM support using given
|
||||
Authkey
|
||||
|
||||
Application Config Options:
|
||||
--plugin arg Plugin(s) to enable, may be specified
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
content_title: How To Attach a YubiHSM Hard Wallet
|
||||
link_text: How To Attach a YubiHSM Hard Wallet
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Attach a YubiHSM as a hard wallet
|
||||
|
||||
## Before you begin
|
||||
|
||||
* Install the currently supported version of `keosd`
|
||||
|
||||
* Install YubiHSM2 Software Toolkit (YubiHSM2 SDK)
|
||||
|
||||
* Create an AuthKey with at least the following Capabilities:
|
||||
|
||||
* sign-ecdsa
|
||||
* generate-asymmetric-key
|
||||
* export-wrapped
|
||||
|
||||
* **Delete the default AuthKey**
|
||||
|
||||
[[warning | Security]]
|
||||
| It is extremely important to create a new AuthKey and remove the default AuthKey before proceed to the following steps.
|
||||
|
||||
## Steps
|
||||
|
||||
### Configure `keosd`
|
||||
|
||||
There are two options to connect `keosd` to YubiHSM:
|
||||
|
||||
#### Using a YubiHSM connector
|
||||
|
||||
By default, `keosd` will connect to the YubiHSM connector on the default host and port. If a non-default URL is used, set the `--yubihsm-url` option or `yubihsm-url` in `config.ini` with the correct connector URL
|
||||
|
||||
#### Directly connect via USB
|
||||
|
||||
`keosd` also can directly connect to YubiHSM via USB protocol
|
||||
|
||||
If this option is used, set `keosd` startup option as the below:
|
||||
|
||||
```sh
|
||||
--yubihsm-url=ysb://
|
||||
```
|
||||
|
||||
### Start `keosd` with AuthKey:
|
||||
|
||||
```sh
|
||||
--yubihsm-authkey Your_AuthKey_Object_Number
|
||||
```
|
||||
|
||||
if a YubiHSM connector is used, check the YubiHSM connector is up and running by visiting YubiHSM URL:
|
||||
http://YubiHSM_HOST:YubiHSM_PORT/connector/status ((Default HOST and Port: http://127.0.0.1:12345)
|
||||
|
||||
You should see something like this:
|
||||
|
||||
```console
|
||||
status=OK
|
||||
serial=*
|
||||
version=2.0.0
|
||||
pid=666
|
||||
address=localhost
|
||||
port=12345
|
||||
```
|
||||
|
||||
### Unlock YubiHSM wallet with the password of AuthKey using the following option:
|
||||
|
||||
```sh
|
||||
cleos wallet unlock -n YubiHSM --password YOUR_AUTHKEY_PASSWORD
|
||||
```
|
||||
|
||||
After unlocking the wallet, you can use `cleos wallet` commands as usual. Beware as a part of security mechanism, some wallet subcommands, such as retrieve private keys, or remove a key, are not supported when a YubiHSM is used
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
content_title: Keosd How-to Guides
|
||||
---
|
||||
|
||||
* [How to attach a YubiHSM hard wallet](how-to-attach-a-yubihsm-hard-wallet.md)
|
||||
+7
-7
@@ -4,8 +4,8 @@
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "EOS.IO"
|
||||
PROJECT_NUMBER = "EOSIO ${DOXY_EOS_VERSION}"
|
||||
PROJECT_NAME = "LEAP"
|
||||
PROJECT_NUMBER = "${DOXY_EOS_VERSION}"
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO = eos-logo.png
|
||||
OUTPUT_DIRECTORY =
|
||||
@@ -209,9 +209,9 @@ HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = io.eos
|
||||
DOCSET_PUBLISHER_ID = one.block
|
||||
DOCSET_PUBLISHER_NAME = block.one
|
||||
DOCSET_BUNDLE_ID = io.antelope
|
||||
DOCSET_PUBLISHER_ID = com.eosnetwork
|
||||
DOCSET_PUBLISHER_NAME = eosnetwork.com
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
@@ -221,14 +221,14 @@ BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = io.eos
|
||||
QHP_NAMESPACE = io.antelope
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = io.eos
|
||||
ECLIPSE_DOC_ID = io.antelope
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
@@ -26,25 +26,3 @@ set(ENABLE_PROFILE OFF CACHE BOOL "Enable for profile builds")
|
||||
if(eos-vm IN_LIST EOSIO_WASM_RUNTIMES OR eos-vm-jit IN_LIST EOSIO_WASM_RUNTIMES)
|
||||
add_subdirectory( eos-vm )
|
||||
endif()
|
||||
|
||||
#yubihsm's openssl discovery is via pkg-config instead of find_package. Help it out on macOS otherwise openssl's pkgconfig
|
||||
# files may not be found down in the /opt/homebrew/opt directory
|
||||
if(APPLE)
|
||||
get_filename_component(OPENSSL_LIB_PATH "${OPENSSL_CRYPTO_LIBRARY}" DIRECTORY)
|
||||
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${OPENSSL_LIB_PATH}/pkgconfig")
|
||||
endif()
|
||||
set(ENABLE_STATIC ON)
|
||||
set(CMAKE_MACOSX_RPATH OFF)
|
||||
set(BUILD_ONLY_LIB ON CACHE BOOL "Library only build")
|
||||
message(STATUS "Starting yubihsm configuration...")
|
||||
add_subdirectory( yubihsm EXCLUDE_FROM_ALL )
|
||||
target_compile_options(yubihsm_static PRIVATE -fno-lto -fcommon)
|
||||
message(STATUS "yubihsm configuration complete")
|
||||
|
||||
get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE)
|
||||
set_property(GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE
|
||||
"change_authkey import_ed decrypt_ec decrypt_rsa ssh logs generate_rsa import_ec echo\
|
||||
yubico_otp wrap_data wrap info import_rsa import_authkey generate_hmac generate_ec\
|
||||
attest pbkdf2 parsing ${_CTEST_CUSTOM_TESTS_IGNORE}")
|
||||
|
||||
add_subdirectory(prometheus)
|
||||
@@ -42,7 +42,7 @@ if("eos-vm-oc" IN_LIST EOSIO_WASM_RUNTIMES)
|
||||
endif()
|
||||
|
||||
llvm_map_components_to_libnames(LLVM_LIBS support core passes mcjit native orcjit)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
|
||||
option(EOSVMOC_ENABLE_DEVELOPER_OPTIONS "enable developer options for EOS VM OC" OFF)
|
||||
|
||||
@@ -75,7 +75,7 @@ void apply_context::exec_one()
|
||||
privileged = receiver_account->is_privileged();
|
||||
auto native = control.find_apply_handler( receiver, act->account, act->name );
|
||||
if( native ) {
|
||||
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
|
||||
if( trx_context.enforce_whiteblacklist && control.is_speculative_block() ) {
|
||||
control.check_contract_list( receiver );
|
||||
control.check_action_list( act->account, act->name );
|
||||
}
|
||||
@@ -89,7 +89,7 @@ void apply_context::exec_one()
|
||||
|| control.is_builtin_activated( builtin_protocol_feature_t::forward_setcode )
|
||||
)
|
||||
) {
|
||||
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
|
||||
if( trx_context.enforce_whiteblacklist && control.is_speculative_block() ) {
|
||||
control.check_contract_list( receiver );
|
||||
control.check_action_list( act->account, act->name );
|
||||
}
|
||||
@@ -316,12 +316,12 @@ void apply_context::execute_inline( action&& a ) {
|
||||
EOS_ASSERT( code != nullptr, action_validate_exception,
|
||||
"inline action's code account ${account} does not exist", ("account", a.account) );
|
||||
|
||||
bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_producing_block();
|
||||
bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_speculative_block();
|
||||
flat_set<account_name> actors;
|
||||
|
||||
bool disallow_send_to_self_bypass = control.is_builtin_activated( builtin_protocol_feature_t::restrict_action_to_self );
|
||||
bool send_to_self = (a.account == receiver);
|
||||
bool inherit_parent_authorizations = (!disallow_send_to_self_bypass && send_to_self && (receiver == act->account) && control.is_producing_block());
|
||||
bool inherit_parent_authorizations = (!disallow_send_to_self_bypass && send_to_self && (receiver == act->account) && control.is_speculative_block());
|
||||
|
||||
flat_set<permission_level> inherited_authorizations;
|
||||
if( inherit_parent_authorizations ) {
|
||||
@@ -347,7 +347,7 @@ void apply_context::execute_inline( action&& a ) {
|
||||
control.check_actor_list( actors );
|
||||
}
|
||||
|
||||
if( !privileged && control.is_producing_block() ) {
|
||||
if( !privileged && control.is_speculative_block() ) {
|
||||
const auto& chain_config = control.get_global_properties().configuration;
|
||||
EOS_ASSERT( a.data.size() < std::min(chain_config.max_inline_action_size, control.get_max_nonprivileged_inline_action_size()),
|
||||
inline_action_too_big_nonprivileged,
|
||||
@@ -373,7 +373,7 @@ void apply_context::execute_inline( action&& a ) {
|
||||
} catch( const fc::exception& e ) {
|
||||
if( disallow_send_to_self_bypass || !send_to_self ) {
|
||||
throw;
|
||||
} else if( control.is_producing_block() ) {
|
||||
} else if( control.is_speculative_block() ) {
|
||||
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with inline action sent to self"));
|
||||
for (const auto& log: e.get_log()) {
|
||||
new_exception.append_log(log);
|
||||
@@ -383,7 +383,7 @@ void apply_context::execute_inline( action&& a ) {
|
||||
} catch( ... ) {
|
||||
if( disallow_send_to_self_bypass || !send_to_self ) {
|
||||
throw;
|
||||
} else if( control.is_producing_block() ) {
|
||||
} else if( control.is_speculative_block() ) {
|
||||
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating inline action sent to self");
|
||||
}
|
||||
}
|
||||
@@ -407,7 +407,7 @@ void apply_context::execute_context_free_inline( action&& a ) {
|
||||
EOS_ASSERT( a.authorization.size() == 0, action_validate_exception,
|
||||
"context-free actions cannot have authorizations" );
|
||||
|
||||
if( !privileged && control.is_producing_block() ) {
|
||||
if( !privileged && control.is_speculative_block() ) {
|
||||
const auto& chain_config = control.get_global_properties().configuration;
|
||||
EOS_ASSERT( a.data.size() < std::min(chain_config.max_inline_action_size, control.get_max_nonprivileged_inline_action_size()),
|
||||
inline_action_too_big_nonprivileged,
|
||||
@@ -428,7 +428,7 @@ void apply_context::execute_context_free_inline( action&& a ) {
|
||||
void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) {
|
||||
EOS_ASSERT( trx.context_free_actions.size() == 0, cfa_inside_generated_tx, "context free actions are not currently allowed in generated transactions" );
|
||||
|
||||
bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_producing_block()
|
||||
bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_speculative_block()
|
||||
&& !control.sender_avoids_whitelist_blacklist_enforcement( receiver );
|
||||
trx_context.validate_referenced_accounts( trx, enforce_actor_whitelist_blacklist );
|
||||
|
||||
@@ -530,7 +530,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
|
||||
} catch( const fc::exception& e ) {
|
||||
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
|
||||
throw;
|
||||
} else if( control.is_producing_block() ) {
|
||||
} else if( control.is_speculative_block() ) {
|
||||
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with sent deferred transaction consisting only of actions to self"));
|
||||
for (const auto& log: e.get_log()) {
|
||||
new_exception.append_log(log);
|
||||
@@ -540,7 +540,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
|
||||
} catch( ... ) {
|
||||
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
|
||||
throw;
|
||||
} else if( control.is_producing_block() ) {
|
||||
} else if( control.is_speculative_block() ) {
|
||||
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating sent deferred transaction consisting only of actions to self");
|
||||
}
|
||||
}
|
||||
@@ -552,7 +552,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
|
||||
|
||||
bool replace_deferred_activated = control.is_builtin_activated(builtin_protocol_feature_t::replace_deferred);
|
||||
|
||||
EOS_ASSERT( replace_deferred_activated || !control.is_producing_block()
|
||||
EOS_ASSERT( replace_deferred_activated || !control.is_speculative_block()
|
||||
|| control.all_subjective_mitigations_disabled(),
|
||||
subjective_block_production_exception,
|
||||
"Replacing a deferred transaction is temporarily disabled." );
|
||||
|
||||
@@ -155,8 +155,9 @@ struct pending_state {
|
||||
|
||||
maybe_session _db_session;
|
||||
block_stage_type _block_stage;
|
||||
controller::block_status _block_status = controller::block_status::incomplete;
|
||||
controller::block_status _block_status = controller::block_status::ephemeral;
|
||||
std::optional<block_id_type> _producer_block_id;
|
||||
controller::block_report _block_report{};
|
||||
|
||||
/** @pre _block_stage cannot hold completed_block alternative */
|
||||
const pending_block_header_state& get_pending_block_header_state()const {
|
||||
@@ -229,8 +230,8 @@ struct controller_impl {
|
||||
protocol_feature_manager protocol_features;
|
||||
controller::config conf;
|
||||
const chain_id_type chain_id; // read by thread_pool threads, value will not be changed
|
||||
std::optional<fc::time_point> replay_head_time;
|
||||
db_read_mode read_mode = db_read_mode::SPECULATIVE;
|
||||
bool replaying = false;
|
||||
db_read_mode read_mode = db_read_mode::HEAD;
|
||||
bool in_trx_requiring_checks = false; ///< if true, checks that are normally skipped on replay (e.g. auth checks) cannot be skipped
|
||||
std::optional<fc::microseconds> subjective_cpu_leeway;
|
||||
bool trusted_producer_light_validation = false;
|
||||
@@ -255,7 +256,7 @@ struct controller_impl {
|
||||
prev = fork_db.root();
|
||||
}
|
||||
|
||||
if ( read_mode == db_read_mode::SPECULATIVE ) {
|
||||
if ( read_mode == db_read_mode::HEAD ) {
|
||||
EOS_ASSERT( head->block, block_validate_exception, "attempting to pop a block that was sparsely loaded from a snapshot");
|
||||
}
|
||||
|
||||
@@ -482,8 +483,7 @@ struct controller_impl {
|
||||
}
|
||||
|
||||
auto blog_head = blog.head();
|
||||
auto blog_head_time = blog_head ? blog_head->timestamp.to_time_point() : fork_db.root()->header.timestamp.to_time_point();
|
||||
replay_head_time = blog_head_time;
|
||||
replaying = true;
|
||||
auto start_block_num = head->block_num + 1;
|
||||
auto start = fc::time_point::now();
|
||||
|
||||
@@ -551,7 +551,7 @@ struct controller_impl {
|
||||
ilog( "replayed ${n} blocks in ${duration} seconds, ${mspb} ms/block",
|
||||
("n", head->block_num + 1 - start_block_num)("duration", (end-start).count()/1000000)
|
||||
("mspb", ((end-start).count()/1000.0)/(head->block_num-start_block_num)) );
|
||||
replay_head_time.reset();
|
||||
replaying = false;
|
||||
|
||||
if( except_ptr ) {
|
||||
std::rethrow_exception( except_ptr );
|
||||
@@ -820,7 +820,10 @@ struct controller_impl {
|
||||
});
|
||||
}
|
||||
|
||||
void add_to_snapshot( const snapshot_writer_ptr& snapshot ) const {
|
||||
void add_to_snapshot( const snapshot_writer_ptr& snapshot ) {
|
||||
// clear in case the previous call to clear did not finish in time of deadline
|
||||
clear_expired_input_transactions( fc::time_point::maximum() );
|
||||
|
||||
snapshot->write_section<chain_snapshot_header>([this]( auto §ion ){
|
||||
section.add_row(chain_snapshot_header(), db);
|
||||
});
|
||||
@@ -993,7 +996,7 @@ struct controller_impl {
|
||||
);
|
||||
}
|
||||
|
||||
sha256 calculate_integrity_hash() const {
|
||||
sha256 calculate_integrity_hash() {
|
||||
sha256::encoder enc;
|
||||
auto hash_writer = std::make_shared<integrity_hash_snapshot_writer>(enc);
|
||||
add_to_snapshot(hash_writer);
|
||||
@@ -1252,7 +1255,8 @@ struct controller_impl {
|
||||
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time = false )
|
||||
{ try {
|
||||
|
||||
const bool validating = !self.is_producing_block();
|
||||
auto start = fc::time_point::now();
|
||||
const bool validating = !self.is_speculative_block();
|
||||
EOS_ASSERT( !validating || explicit_billed_cpu_time, transaction_exception, "validating requires explicit billing" );
|
||||
|
||||
maybe_session undo_session;
|
||||
@@ -1291,6 +1295,10 @@ struct controller_impl {
|
||||
trace->scheduled = true;
|
||||
trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::expired, billed_cpu_time_us, 0 ); // expire the transaction
|
||||
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
pending->_block_report.total_cpu_usage_us += billed_cpu_time_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += trace->elapsed;
|
||||
emit( self.accepted_transaction, trx );
|
||||
dmlog_applied_transaction(trace);
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
@@ -1321,7 +1329,7 @@ struct controller_impl {
|
||||
trace->error_code = controller::convert_exception_to_error_code( e );
|
||||
trace->except = e;
|
||||
trace->except_ptr = std::current_exception();
|
||||
trace->elapsed = fc::time_point::now() - trx_context.start;
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
|
||||
if (auto dm_logger = get_deep_mind_logger()) {
|
||||
dm_logger->on_fail_deferred();
|
||||
@@ -1331,7 +1339,7 @@ struct controller_impl {
|
||||
try {
|
||||
trx_context.init_for_deferred_trx( gtrx.published );
|
||||
|
||||
if( trx_context.enforce_whiteblacklist && pending->_block_status == controller::block_status::incomplete ) {
|
||||
if( trx_context.enforce_whiteblacklist && self.is_speculative_block() ) {
|
||||
flat_set<account_name> actors;
|
||||
for( const auto& act : trx->packed_trx()->get_transaction().actions ) {
|
||||
for( const auto& auth : act.authorization ) {
|
||||
@@ -1365,6 +1373,11 @@ struct controller_impl {
|
||||
|
||||
restore.cancel();
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
|
||||
return trace;
|
||||
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
|
||||
throw;
|
||||
@@ -1395,13 +1408,18 @@ struct controller_impl {
|
||||
trace = error_trace;
|
||||
if( !trace->except_ptr ) {
|
||||
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
emit( self.accepted_transaction, trx );
|
||||
dmlog_applied_transaction(trace);
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
undo_session.squash();
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += trace->elapsed;
|
||||
return trace;
|
||||
}
|
||||
trace->elapsed = fc::time_point::now() - trx_context.start;
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
}
|
||||
|
||||
// Only subjective OR hard failure logic below:
|
||||
@@ -1448,6 +1466,11 @@ struct controller_impl {
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
}
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
|
||||
return trace;
|
||||
} FC_CAPTURE_AND_RETHROW() } /// push_scheduled_transaction
|
||||
|
||||
@@ -1505,7 +1528,7 @@ struct controller_impl {
|
||||
const signed_transaction& trn = trx->packed_trx()->get_signed_transaction();
|
||||
transaction_checktime_timer trx_timer(timer);
|
||||
transaction_context trx_context(self, *trx->packed_trx(), std::move(trx_timer), start, trx->read_only);
|
||||
if ((bool)subjective_cpu_leeway && pending->_block_status == controller::block_status::incomplete) {
|
||||
if ((bool)subjective_cpu_leeway && self.is_speculative_block()) {
|
||||
trx_context.leeway = *subjective_cpu_leeway;
|
||||
}
|
||||
trx_context.block_deadline = block_deadline;
|
||||
@@ -1528,10 +1551,8 @@ struct controller_impl {
|
||||
trx_context.init_for_implicit_trx();
|
||||
trx_context.enforce_whiteblacklist = false;
|
||||
} else {
|
||||
bool skip_recording = replay_head_time && (time_point(trn.expiration) < *replay_head_time);
|
||||
trx_context.init_for_input_trx( trx->packed_trx()->get_unprunable_size(),
|
||||
trx->packed_trx()->get_prunable_size(),
|
||||
skip_recording);
|
||||
trx->packed_trx()->get_prunable_size() );
|
||||
}
|
||||
|
||||
trx_context.delay = fc::seconds(trn.delay_sec);
|
||||
@@ -1582,14 +1603,28 @@ struct controller_impl {
|
||||
}
|
||||
|
||||
|
||||
if ( (read_mode != db_read_mode::SPECULATIVE && pending->_block_status == controller::block_status::incomplete) || trx->read_only ) {
|
||||
//this may happen automatically in destructor, but I prefer make it more explicit
|
||||
trx_context.undo();
|
||||
if ( trx->read_only ) {
|
||||
// remove trx from pending block by not canceling 'restore'
|
||||
trx_context.undo(); // this will happen automatically in destructor, but make it more explicit
|
||||
} else if ( pending->_block_status == controller::block_status::ephemeral ) {
|
||||
// An ephemeral block will never become a full block, but on a producer node the trxs should be saved
|
||||
// in the un-applied transaction queue for execution during block production. For a non-producer node
|
||||
// save the trxs in the un-applied transaction queue for use during block validation to skip signature
|
||||
// recovery.
|
||||
restore.cancel(); // maintain trx metas for abort block
|
||||
trx_context.undo(); // this will happen automatically in destructor, but make it more explicit
|
||||
} else {
|
||||
restore.cancel();
|
||||
trx_context.squash();
|
||||
}
|
||||
|
||||
if( !trx->read_only ) {
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
}
|
||||
|
||||
return trace;
|
||||
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
|
||||
throw;
|
||||
@@ -1607,9 +1642,14 @@ struct controller_impl {
|
||||
}
|
||||
|
||||
if (!trx->read_only) {
|
||||
emit(self.accepted_transaction, trx);
|
||||
dmlog_applied_transaction(trace);
|
||||
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
|
||||
emit(self.accepted_transaction, trx);
|
||||
dmlog_applied_transaction(trace);
|
||||
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
}
|
||||
|
||||
return trace;
|
||||
@@ -1652,8 +1692,9 @@ struct controller_impl {
|
||||
auto& bb = std::get<building_block>(pending->_block_stage);
|
||||
const auto& pbhs = bb._pending_block_header_state;
|
||||
|
||||
// modify state of speculative block only if we are in speculative read mode (otherwise we need clean state for head or read-only modes)
|
||||
if ( read_mode == db_read_mode::SPECULATIVE || pending->_block_status != controller::block_status::incomplete )
|
||||
// block status is either ephemeral or incomplete. Modify state of speculative block only if we are building a
|
||||
// speculative incomplete block (otherwise we need clean state for head mode, ephemeral block)
|
||||
if ( pending->_block_status != controller::block_status::ephemeral )
|
||||
{
|
||||
const auto& pso = db.get<protocol_state_object>();
|
||||
|
||||
@@ -1729,7 +1770,7 @@ struct controller_impl {
|
||||
)
|
||||
{
|
||||
// Promote proposed schedule to pending schedule.
|
||||
if( !replay_head_time ) {
|
||||
if( !replaying ) {
|
||||
ilog( "promoting proposed schedule (set in block ${proposed_num}) to pending; current block: ${n} lib: ${lib} schedule: ${schedule} ",
|
||||
("proposed_num", *gpo.proposed_schedule_block_num)("n", pbhs.block_num)
|
||||
("lib", pbhs.dpos_irreversible_blocknum)
|
||||
@@ -2063,12 +2104,6 @@ struct controller_impl {
|
||||
EOS_ASSERT( r == static_cast<const transaction_receipt_header&>(receipt),
|
||||
block_validate_exception, "receipt does not match, ${lhs} != ${rhs}",
|
||||
("lhs", r)("rhs", static_cast<const transaction_receipt_header&>(receipt)) );
|
||||
|
||||
if( trace ) {
|
||||
br.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) br.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
br.total_elapsed_time += trace->elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
finalize_block();
|
||||
@@ -2089,6 +2124,7 @@ struct controller_impl {
|
||||
// create completed_block with the existing block_state as we just verified it is the same as assembled_block
|
||||
pending->_block_stage = completed_block{ bsp };
|
||||
|
||||
br = pending->_block_report; // copy before commit block destroys pending
|
||||
commit_block(false);
|
||||
br.total_time = fc::time_point::now() - start;
|
||||
return;
|
||||
@@ -2394,7 +2430,7 @@ struct controller_impl {
|
||||
//Look for expired transactions in the deduplication list, and remove them.
|
||||
auto& transaction_idx = db.get_mutable_index<transaction_multi_index>();
|
||||
const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
|
||||
auto now = self.pending_block_time();
|
||||
auto now = self.is_building_block() ? self.pending_block_time() : self.head_block_time();
|
||||
const auto total = dedupe_index.size();
|
||||
uint32_t num_removed = 0;
|
||||
while( (!dedupe_index.empty()) && ( now > fc::time_point(dedupe_index.begin()->expiration) ) ) {
|
||||
@@ -2670,7 +2706,7 @@ void controller::preactivate_feature( const digest_type& feature_digest ) {
|
||||
auto status = pfs.is_recognized( feature_digest, cur_time );
|
||||
switch( status ) {
|
||||
case protocol_feature_set::recognized_t::unrecognized:
|
||||
if( is_producing_block() ) {
|
||||
if( is_speculative_block() ) {
|
||||
EOS_THROW( subjective_block_production_exception,
|
||||
"protocol feature with digest '${digest}' is unrecognized", ("digest", feature_digest) );
|
||||
} else {
|
||||
@@ -2679,7 +2715,7 @@ void controller::preactivate_feature( const digest_type& feature_digest ) {
|
||||
}
|
||||
break;
|
||||
case protocol_feature_set::recognized_t::disabled:
|
||||
if( is_producing_block() ) {
|
||||
if( is_speculative_block() ) {
|
||||
EOS_THROW( subjective_block_production_exception,
|
||||
"protocol feature with digest '${digest}' is disabled", ("digest", feature_digest) );
|
||||
} else {
|
||||
@@ -2688,7 +2724,7 @@ void controller::preactivate_feature( const digest_type& feature_digest ) {
|
||||
}
|
||||
break;
|
||||
case protocol_feature_set::recognized_t::too_early:
|
||||
if( is_producing_block() ) {
|
||||
if( is_speculative_block() ) {
|
||||
EOS_THROW( subjective_block_production_exception,
|
||||
"${timestamp} is too early for the earliest allowed activation time of the protocol feature with digest '${digest}'", ("digest", feature_digest)("timestamp", cur_time) );
|
||||
} else {
|
||||
@@ -2699,7 +2735,7 @@ void controller::preactivate_feature( const digest_type& feature_digest ) {
|
||||
case protocol_feature_set::recognized_t::ready:
|
||||
break;
|
||||
default:
|
||||
if( is_producing_block() ) {
|
||||
if( is_speculative_block() ) {
|
||||
EOS_THROW( subjective_block_production_exception, "unexpected recognized_t status" );
|
||||
} else {
|
||||
EOS_THROW( protocol_feature_bad_block_exception, "unexpected recognized_t status" );
|
||||
@@ -2791,32 +2827,10 @@ void controller::validate_protocol_features( const vector<digest_type>& features
|
||||
features_to_activate );
|
||||
}
|
||||
|
||||
void controller::start_block( block_timestamp_type when, uint16_t confirm_block_count )
|
||||
{
|
||||
validate_db_available_size();
|
||||
|
||||
EOS_ASSERT( !my->pending, block_validate_exception, "pending block already exists" );
|
||||
|
||||
vector<digest_type> new_protocol_feature_activations;
|
||||
|
||||
const auto& pso = my->db.get<protocol_state_object>();
|
||||
if( pso.preactivated_protocol_features.size() > 0 ) {
|
||||
for( const auto& f : pso.preactivated_protocol_features ) {
|
||||
new_protocol_feature_activations.emplace_back( f );
|
||||
}
|
||||
}
|
||||
|
||||
if( new_protocol_feature_activations.size() > 0 ) {
|
||||
validate_protocol_features( new_protocol_feature_activations );
|
||||
}
|
||||
|
||||
my->start_block( when, confirm_block_count, new_protocol_feature_activations,
|
||||
block_status::incomplete, std::optional<block_id_type>(), fc::time_point::maximum() );
|
||||
}
|
||||
|
||||
void controller::start_block( block_timestamp_type when,
|
||||
uint16_t confirm_block_count,
|
||||
const vector<digest_type>& new_protocol_feature_activations,
|
||||
block_status bs,
|
||||
const fc::time_point& deadline )
|
||||
{
|
||||
validate_db_available_size();
|
||||
@@ -2825,11 +2839,13 @@ void controller::start_block( block_timestamp_type when,
|
||||
validate_protocol_features( new_protocol_feature_activations );
|
||||
}
|
||||
|
||||
EOS_ASSERT( bs == block_status::incomplete || bs == block_status::ephemeral, block_validate_exception, "speculative block type required" );
|
||||
|
||||
my->start_block( when, confirm_block_count, new_protocol_feature_activations,
|
||||
block_status::incomplete, std::optional<block_id_type>(), deadline );
|
||||
bs, std::optional<block_id_type>(), deadline );
|
||||
}
|
||||
|
||||
block_state_ptr controller::finalize_block( const signer_callback_type& signer_callback ) {
|
||||
block_state_ptr controller::finalize_block( block_report& br, const signer_callback_type& signer_callback ) {
|
||||
validate_db_available_size();
|
||||
|
||||
my->finalize_block();
|
||||
@@ -2850,6 +2866,8 @@ block_state_ptr controller::finalize_block( const signer_callback_type& signer_c
|
||||
|
||||
my->pending->_block_stage = completed_block{ bsp };
|
||||
|
||||
br = my->pending->_block_report;
|
||||
|
||||
return bsp;
|
||||
}
|
||||
|
||||
@@ -3104,11 +3122,11 @@ block_id_type controller::get_block_id_for_num( uint32_t block_num )const { try
|
||||
return id;
|
||||
} FC_CAPTURE_AND_RETHROW( (block_num) ) }
|
||||
|
||||
sha256 controller::calculate_integrity_hash()const { try {
|
||||
sha256 controller::calculate_integrity_hash() { try {
|
||||
return my->calculate_integrity_hash();
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
void controller::write_snapshot( const snapshot_writer_ptr& snapshot ) const {
|
||||
void controller::write_snapshot( const snapshot_writer_ptr& snapshot ) {
|
||||
EOS_ASSERT( !my->pending, block_validate_exception, "cannot take a consistent snapshot with a pending block" );
|
||||
return my->add_to_snapshot(snapshot);
|
||||
}
|
||||
@@ -3317,14 +3335,14 @@ bool controller::is_building_block()const {
|
||||
return my->pending.has_value();
|
||||
}
|
||||
|
||||
bool controller::is_producing_block()const {
|
||||
bool controller::is_speculative_block()const {
|
||||
if( !my->pending ) return false;
|
||||
|
||||
return (my->pending->_block_status == block_status::incomplete);
|
||||
return (my->pending->_block_status == block_status::incomplete || my->pending->_block_status == block_status::ephemeral );
|
||||
}
|
||||
|
||||
bool controller::is_ram_billing_in_notify_allowed()const {
|
||||
return my->conf.disable_all_subjective_mitigations || !is_producing_block() || my->conf.allow_ram_billing_in_notify;
|
||||
return my->conf.disable_all_subjective_mitigations || !is_speculative_block() || my->conf.allow_ram_billing_in_notify;
|
||||
}
|
||||
|
||||
uint32_t controller::configured_subjective_signature_length_limit()const {
|
||||
|
||||
@@ -54,7 +54,7 @@ void validate_authority_precondition( const apply_context& context, const author
|
||||
}
|
||||
}
|
||||
|
||||
if( context.trx_context.enforce_whiteblacklist && context.control.is_producing_block() ) {
|
||||
if( context.trx_context.enforce_whiteblacklist && context.control.is_speculative_block() ) {
|
||||
for( const auto& p : auth.keys ) {
|
||||
context.control.check_key_list( p.key );
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ namespace eosio { namespace chain {
|
||||
class fork_database;
|
||||
|
||||
enum class db_read_mode {
|
||||
SPECULATIVE,
|
||||
HEAD,
|
||||
READ_ONLY,
|
||||
IRREVERSIBLE
|
||||
};
|
||||
|
||||
@@ -92,7 +90,7 @@ namespace eosio { namespace chain {
|
||||
eosvmoc::config eosvmoc_config;
|
||||
bool eosvmoc_tierup = false;
|
||||
|
||||
db_read_mode read_mode = db_read_mode::SPECULATIVE;
|
||||
db_read_mode read_mode = db_read_mode::HEAD;
|
||||
validation_mode block_validation_mode = validation_mode::FULL;
|
||||
|
||||
pinnable_mapped_file::map_mode db_map_mode = pinnable_mapped_file::map_mode::mapped;
|
||||
@@ -108,7 +106,8 @@ namespace eosio { namespace chain {
|
||||
irreversible = 0, ///< this block has already been applied before by this node and is considered irreversible
|
||||
validated = 1, ///< this is a complete block signed by a valid producer and has been previously applied by this node and therefore validated but it is not yet irreversible
|
||||
complete = 2, ///< this is a complete block signed by a valid producer but is not yet irreversible nor has it yet been applied by this node
|
||||
incomplete = 3, ///< this is an incomplete block (either being produced by a producer or speculatively produced by a node)
|
||||
incomplete = 3, ///< this is an incomplete block being produced by a producer
|
||||
ephemeral = 4 ///< this is an incomplete block created for speculative execution of trxs, will always be aborted
|
||||
};
|
||||
|
||||
controller( const config& cfg, const chain_id_type& chain_id );
|
||||
@@ -127,20 +126,12 @@ namespace eosio { namespace chain {
|
||||
void validate_protocol_features( const vector<digest_type>& features_to_activate )const;
|
||||
|
||||
/**
|
||||
* Starts a new pending block session upon which new transactions can
|
||||
* be pushed.
|
||||
*
|
||||
* Will only activate protocol features that have been pre-activated.
|
||||
*/
|
||||
void start_block( block_timestamp_type time = block_timestamp_type(), uint16_t confirm_block_count = 0 );
|
||||
|
||||
/**
|
||||
* Starts a new pending block session upon which new transactions can
|
||||
* be pushed.
|
||||
* Starts a new pending block session upon which new transactions can be pushed.
|
||||
*/
|
||||
void start_block( block_timestamp_type time,
|
||||
uint16_t confirm_block_count,
|
||||
const vector<digest_type>& new_protocol_feature_activations,
|
||||
block_status bs,
|
||||
const fc::time_point& deadline = fc::time_point::maximum() );
|
||||
|
||||
/**
|
||||
@@ -164,18 +155,19 @@ namespace eosio { namespace chain {
|
||||
fc::time_point block_deadline, fc::microseconds max_transaction_time,
|
||||
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time );
|
||||
|
||||
block_state_ptr finalize_block( const signer_callback_type& signer_callback );
|
||||
void sign_block( const signer_callback_type& signer_callback );
|
||||
void commit_block();
|
||||
|
||||
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
|
||||
|
||||
struct block_report {
|
||||
size_t total_net_usage = 0;
|
||||
size_t total_cpu_usage_us = 0;
|
||||
fc::microseconds total_elapsed_time{};
|
||||
fc::microseconds total_time{};
|
||||
};
|
||||
|
||||
block_state_ptr finalize_block( block_report& br, const signer_callback_type& signer_callback );
|
||||
void sign_block( const signer_callback_type& signer_callback );
|
||||
void commit_block();
|
||||
|
||||
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
|
||||
|
||||
/**
|
||||
* @param br returns statistics for block
|
||||
* @param block_state_future provide from call to create_block_state_future
|
||||
@@ -256,8 +248,8 @@ namespace eosio { namespace chain {
|
||||
|
||||
block_id_type get_block_id_for_num( uint32_t block_num )const;
|
||||
|
||||
sha256 calculate_integrity_hash()const;
|
||||
void write_snapshot( const snapshot_writer_ptr& snapshot )const;
|
||||
sha256 calculate_integrity_hash();
|
||||
void write_snapshot( const snapshot_writer_ptr& snapshot );
|
||||
|
||||
bool sender_avoids_whitelist_blacklist_enforcement( account_name sender )const;
|
||||
void check_actor_list( const flat_set<account_name>& actors )const;
|
||||
@@ -265,7 +257,7 @@ namespace eosio { namespace chain {
|
||||
void check_action_list( account_name code, action_name action )const;
|
||||
void check_key_list( const public_key_type& key )const;
|
||||
bool is_building_block()const;
|
||||
bool is_producing_block()const;
|
||||
bool is_speculative_block()const;
|
||||
|
||||
bool is_ram_billing_in_notify_allowed()const;
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ namespace eosio { namespace chain {
|
||||
void init_for_implicit_trx( uint64_t initial_net_usage = 0 );
|
||||
|
||||
void init_for_input_trx( uint64_t packed_trx_unprunable_size,
|
||||
uint64_t packed_trx_prunable_size,
|
||||
bool skip_recording);
|
||||
uint64_t packed_trx_prunable_size );
|
||||
|
||||
void init_for_deferred_trx( fc::time_point published );
|
||||
|
||||
|
||||
@@ -21,11 +21,10 @@ using namespace boost::multi_index;
|
||||
|
||||
enum class trx_enum_type {
|
||||
unknown = 0,
|
||||
persisted = 1,
|
||||
forked = 2,
|
||||
aborted = 3,
|
||||
incoming_persisted = 4,
|
||||
incoming = 5 // incoming_end() needs to be updated if this changes
|
||||
forked = 1,
|
||||
aborted = 2,
|
||||
incoming_api = 3,
|
||||
incoming_p2p = 4 // incoming_end() needs to be updated if this changes
|
||||
};
|
||||
|
||||
using next_func_t = std::function<void(const std::variant<fc::exception_ptr, transaction_trace_ptr>&)>;
|
||||
@@ -46,8 +45,7 @@ struct unapplied_transaction {
|
||||
};
|
||||
|
||||
/**
|
||||
* Track unapplied transactions for persisted, forked blocks, and aborted blocks.
|
||||
* Persisted are first so that they can be applied in each block until expired.
|
||||
* Track unapplied transactions for incoming, forked blocks, and aborted blocks.
|
||||
*/
|
||||
class unapplied_transaction_queue {
|
||||
private:
|
||||
@@ -159,26 +157,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void add_persisted( const transaction_metadata_ptr& trx ) {
|
||||
auto itr = queue.get<by_trx_id>().find( trx->id() );
|
||||
if( itr == queue.get<by_trx_id>().end() ) {
|
||||
auto insert_itr = queue.insert( { trx, trx_enum_type::persisted } );
|
||||
if( insert_itr.second ) added( insert_itr.first );
|
||||
} else if( itr->trx_type != trx_enum_type::persisted ) {
|
||||
if (itr->trx_type == trx_enum_type::incoming || itr->trx_type == trx_enum_type::incoming_persisted)
|
||||
--incoming_count;
|
||||
queue.get<by_trx_id>().modify( itr, [](auto& un){
|
||||
un.trx_type = trx_enum_type::persisted;
|
||||
un.next = nullptr; // persisted already have ack'ed initial trace
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
void add_incoming( const transaction_metadata_ptr& trx, bool persist_until_expired, bool return_failure_trace, next_func_t next ) {
|
||||
void add_incoming( const transaction_metadata_ptr& trx, bool api_trx, bool return_failure_trace, next_func_t next ) {
|
||||
auto itr = queue.get<by_trx_id>().find( trx->id() );
|
||||
if( itr == queue.get<by_trx_id>().end() ) {
|
||||
auto insert_itr = queue.insert(
|
||||
{ trx, persist_until_expired ? trx_enum_type::incoming_persisted : trx_enum_type::incoming, return_failure_trace, std::move( next ) } );
|
||||
{ trx, api_trx ? trx_enum_type::incoming_api : trx_enum_type::incoming_p2p, return_failure_trace, std::move( next ) } );
|
||||
if( insert_itr.second ) added( insert_itr.first );
|
||||
} else {
|
||||
if( itr->trx_meta == trx ) return; // same trx meta pointer
|
||||
@@ -194,14 +177,11 @@ public:
|
||||
iterator begin() { return queue.get<by_type>().begin(); }
|
||||
iterator end() { return queue.get<by_type>().end(); }
|
||||
|
||||
// persisted, forked, aborted
|
||||
// forked, aborted
|
||||
iterator unapplied_begin() { return queue.get<by_type>().begin(); }
|
||||
iterator unapplied_end() { return queue.get<by_type>().upper_bound( trx_enum_type::aborted ); }
|
||||
|
||||
iterator persisted_begin() { return queue.get<by_type>().lower_bound( trx_enum_type::persisted ); }
|
||||
iterator persisted_end() { return queue.get<by_type>().upper_bound( trx_enum_type::persisted ); }
|
||||
|
||||
iterator incoming_begin() { return queue.get<by_type>().lower_bound( trx_enum_type::incoming_persisted ); }
|
||||
iterator incoming_begin() { return queue.get<by_type>().lower_bound( trx_enum_type::incoming_api ); }
|
||||
iterator incoming_end() { return queue.get<by_type>().end(); } // if changed to upper_bound, verify usage performance
|
||||
|
||||
iterator lower_bound( const transaction_id_type& id ) {
|
||||
@@ -220,7 +200,7 @@ private:
|
||||
template<typename Itr>
|
||||
void added( Itr itr ) {
|
||||
auto size = calc_size( itr->trx_meta );
|
||||
if( itr->trx_type == trx_enum_type::incoming || itr->trx_type == trx_enum_type::incoming_persisted ) {
|
||||
if( itr->trx_type == trx_enum_type::incoming_p2p || itr->trx_type == trx_enum_type::incoming_api ) {
|
||||
++incoming_count;
|
||||
EOS_ASSERT( size_in_bytes + size < max_transaction_queue_size, tx_resource_exhaustion,
|
||||
"Transaction ${id}, size ${s} bytes would exceed configured "
|
||||
@@ -233,7 +213,7 @@ private:
|
||||
|
||||
template<typename Itr>
|
||||
void removed( Itr itr ) {
|
||||
if( itr->trx_type == trx_enum_type::incoming || itr->trx_type == trx_enum_type::incoming_persisted ) {
|
||||
if( itr->trx_type == trx_enum_type::incoming_p2p || itr->trx_type == trx_enum_type::incoming_api ) {
|
||||
--incoming_count;
|
||||
}
|
||||
size_in_bytes -= calc_size( itr->trx_meta );
|
||||
|
||||
@@ -332,7 +332,7 @@ namespace eosio { namespace chain { namespace wasm_validations {
|
||||
public:
|
||||
wasm_binary_validation( const eosio::chain::controller& control, IR::Module& mod ) : _module( &mod ) {
|
||||
// initialize validators here
|
||||
nested_validator::init(!control.is_producing_block());
|
||||
nested_validator::init(!control.is_speculative_block());
|
||||
}
|
||||
|
||||
void validate() {
|
||||
|
||||
@@ -349,7 +349,13 @@ auto fn(A... a) {
|
||||
: "cc");
|
||||
}
|
||||
using native_args = vm::flatten_parameters_t<AUTO_PARAM_WORKAROUND(F)>;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-value"
|
||||
// If a is unpopulated, this reports "statement has no effect [-Werror=unused-value]"
|
||||
eosio::vm::native_value stack[] = { a... };
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
constexpr int cb_ctx_ptr_offset = OFFSET_OF_CONTROL_BLOCK_MEMBER(ctx);
|
||||
apply_context* ctx;
|
||||
asm("mov %%gs:%c[applyContextOffset], %[cPtr]\n"
|
||||
@@ -385,7 +391,7 @@ void register_eosvm_oc(Name n) {
|
||||
if(n == BOOST_HANA_STRING("env.eosio_exit")) return;
|
||||
constexpr auto fn = create_function<F, Preconditions, injected>();
|
||||
constexpr auto index = find_intrinsic_index(n.c_str());
|
||||
intrinsic the_intrinsic(
|
||||
[[maybe_unused]] intrinsic the_intrinsic(
|
||||
n.c_str(),
|
||||
wasm_function_type_provider<std::remove_pointer_t<decltype(fn)>>::type(),
|
||||
reinterpret_cast<void*>(fn),
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace eosio { namespace chain {
|
||||
}
|
||||
|
||||
void transaction_context::disallow_transaction_extensions( const char* error_msg )const {
|
||||
if( control.is_producing_block() ) {
|
||||
if( control.is_speculative_block() ) {
|
||||
EOS_THROW( subjective_block_production_exception, error_msg );
|
||||
} else {
|
||||
EOS_THROW( disallowed_transaction_extensions_bad_block_exception, error_msg );
|
||||
@@ -234,8 +234,7 @@ namespace eosio { namespace chain {
|
||||
}
|
||||
|
||||
void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size,
|
||||
uint64_t packed_trx_prunable_size,
|
||||
bool skip_recording )
|
||||
uint64_t packed_trx_prunable_size )
|
||||
{
|
||||
const transaction& trx = packed_trx.get_transaction();
|
||||
if( trx.transaction_extensions.size() > 0 ) {
|
||||
@@ -269,11 +268,10 @@ namespace eosio { namespace chain {
|
||||
if (!control.skip_trx_checks()) {
|
||||
control.validate_expiration(trx);
|
||||
control.validate_tapos(trx);
|
||||
validate_referenced_accounts( trx, enforce_whiteblacklist && control.is_producing_block() );
|
||||
validate_referenced_accounts( trx, enforce_whiteblacklist && control.is_speculative_block() );
|
||||
}
|
||||
init( initial_net_usage);
|
||||
if (!skip_recording)
|
||||
record_transaction( packed_trx.id(), trx.expiration ); /// checks for dupes
|
||||
record_transaction( packed_trx.id(), trx.expiration ); /// checks for dupes
|
||||
}
|
||||
|
||||
void transaction_context::init_for_deferred_trx( fc::time_point p )
|
||||
@@ -587,7 +585,7 @@ namespace eosio { namespace chain {
|
||||
uint32_t specified_greylist_limit = control.get_greylist_limit();
|
||||
for( const auto& a : bill_to_accounts ) {
|
||||
uint32_t greylist_limit = config::maximum_elastic_resource_multiplier;
|
||||
if( !force_elastic_limits && control.is_producing_block() ) {
|
||||
if( !force_elastic_limits && control.is_speculative_block() ) {
|
||||
if( control.is_resource_greylisted(a) ) {
|
||||
greylist_limit = 1;
|
||||
} else {
|
||||
@@ -606,7 +604,7 @@ namespace eosio { namespace chain {
|
||||
}
|
||||
}
|
||||
|
||||
EOS_ASSERT( (!force_elastic_limits && control.is_producing_block()) || (!greylisted_cpu && !greylisted_net),
|
||||
EOS_ASSERT( (!force_elastic_limits && control.is_speculative_block()) || (!greylisted_cpu && !greylisted_net),
|
||||
transaction_exception, "greylisted when not producing block" );
|
||||
|
||||
return std::make_tuple(account_net_limit, account_cpu_limit, greylisted_net, greylisted_cpu);
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace eosio { namespace chain { namespace webassembly {
|
||||
EOS_ASSERT(p.which() < context.db.get<protocol_state_object>().num_supported_key_types, unactivated_key_type,
|
||||
"Unactivated key type used when creating assert_recover_key");
|
||||
|
||||
if(context.control.is_producing_block())
|
||||
if(context.control.is_speculative_block())
|
||||
EOS_ASSERT(s.variable_size() <= context.control.configured_subjective_signature_length_limit(),
|
||||
sig_variable_size_limit_exception, "signature variable length component size greater than subjective maximum");
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace eosio { namespace chain { namespace webassembly {
|
||||
EOS_ASSERT(s.which() < context.db.get<protocol_state_object>().num_supported_key_types, unactivated_signature_type,
|
||||
"Unactivated signature type used during recover_key");
|
||||
|
||||
if(context.control.is_producing_block())
|
||||
if(context.control.is_speculative_block())
|
||||
EOS_ASSERT(s.variable_size() <= context.control.configured_subjective_signature_length_limit(),
|
||||
sig_variable_size_limit_exception, "signature variable length component size greater than subjective maximum");
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace eosio { namespace chain { namespace webassembly {
|
||||
span<const char> exp,
|
||||
span<const char> modulus,
|
||||
span<char> out) const {
|
||||
if (context.control.is_producing_block()) {
|
||||
if (context.control.is_speculative_block()) {
|
||||
unsigned int base_modulus_size = std::max(base.size(), modulus.size());
|
||||
|
||||
if (base_modulus_size < exp.size()) {
|
||||
|
||||
+1
-1
Submodule libraries/chainbase updated: 62d3f99059...1f058fff94
@@ -3,7 +3,7 @@
|
||||
// https://github.com/CLIUtils/CLI11
|
||||
//
|
||||
// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
|
||||
// from: 1d3b0a7
|
||||
// from: b19d133
|
||||
//
|
||||
// CLI11 2.2.0 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry
|
||||
// Schreiner under NSF AWARD 1414736. All rights reserved.
|
||||
@@ -34,28 +34,28 @@
|
||||
#pragma once
|
||||
|
||||
// Standard combined includes:
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
#include <iomanip>
|
||||
#include <locale>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <locale>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <utility>
|
||||
|
||||
|
||||
#define CLI11_VERSION_MAJOR 2
|
||||
@@ -9420,4 +9420,134 @@ inline std::string Formatter::make_option_usage(const Option *opt) const {
|
||||
|
||||
|
||||
|
||||
|
||||
class LeapFormatter : public Formatter {
|
||||
// pseudographics - to draw subcommand tree
|
||||
const char* tree_line = u8"\u2502";
|
||||
const char* tree_angle = u8"\u2514";
|
||||
const char* tree_fork = u8"\u251C";
|
||||
|
||||
public:
|
||||
LeapFormatter() : Formatter() {
|
||||
// this gives better, more compact display
|
||||
column_width(25);
|
||||
}
|
||||
LeapFormatter(const LeapFormatter&) = default;
|
||||
LeapFormatter(LeapFormatter&&) = default;
|
||||
|
||||
/// This prints out all the subcommands
|
||||
virtual std::string make_subcommands(const App* app, AppFormatMode mode) const {
|
||||
std::stringstream out;
|
||||
|
||||
std::vector<const App*> subcommands = app->get_subcommands({});
|
||||
|
||||
// Make a list in definition order of the groups seen
|
||||
std::vector<std::string> subcmd_groups_seen;
|
||||
for(const App* com: subcommands) {
|
||||
if(com->get_name().empty()) {
|
||||
if(!com->get_group().empty()) {
|
||||
out << make_expanded(com);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::string group_key = com->get_group();
|
||||
if(!group_key.empty() &&
|
||||
std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
|
||||
return detail::to_lower(a) == detail::to_lower(group_key);
|
||||
}) == subcmd_groups_seen.end())
|
||||
subcmd_groups_seen.push_back(group_key);
|
||||
}
|
||||
|
||||
// For each group, filter out and print subcommands
|
||||
for(const std::string& group: subcmd_groups_seen) {
|
||||
if(mode != AppFormatMode::SubCompact) {// do not show "Subcommands" header for nested tems in compact mode
|
||||
out << "\n"
|
||||
<< group << ":\n";
|
||||
}
|
||||
std::vector<const App*> subcommands_group = app->get_subcommands([&group](const App* sub_app) {
|
||||
return detail::to_lower(sub_app->get_group()) == detail::to_lower(group);
|
||||
});
|
||||
for(const App* new_com: subcommands_group) {
|
||||
if(new_com->get_name().empty())
|
||||
continue;
|
||||
|
||||
std::string tree_symbol = (subcommands_group.back() == new_com ? tree_angle : tree_fork);
|
||||
std::string line_symbol = (subcommands_group.back() == new_com ? "" : tree_line);
|
||||
std::string subc_symbol = "";
|
||||
|
||||
const App* parent = app->get_parent();
|
||||
if(parent != nullptr) {
|
||||
std::vector<const App*> sc_group = parent->get_subcommands([&group](const App* sub_app) {
|
||||
return detail::to_lower(sub_app->get_group()) == detail::to_lower(group);
|
||||
});
|
||||
if(sc_group.back() != app) {
|
||||
subc_symbol = tree_line;
|
||||
}
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case AppFormatMode::All:
|
||||
out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::Sub);
|
||||
out << "\n";
|
||||
break;
|
||||
case AppFormatMode::AllCompact:
|
||||
|
||||
out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::SubCompact);
|
||||
out << line_symbol;
|
||||
out << "\n";
|
||||
break;
|
||||
case AppFormatMode::Normal:
|
||||
case AppFormatMode::Sub:
|
||||
out << make_subcommand(new_com);
|
||||
break;
|
||||
case AppFormatMode::SubCompact:
|
||||
out << tree_symbol << make_expanded(new_com, mode);
|
||||
break;
|
||||
default:
|
||||
throw HorribleError("Internal error: unknown help type requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// This prints out a subcommand in help-all
|
||||
virtual std::string make_expanded(const App* sub, AppFormatMode mode = AppFormatMode::Sub) const {
|
||||
std::stringstream out;
|
||||
std::string tmp;
|
||||
std::string subc_symbol = " ";
|
||||
if(mode == AppFormatMode::SubCompact) {
|
||||
detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
|
||||
out << make_subcommands(sub, mode);
|
||||
} else {
|
||||
out << sub->get_display_name(true) << "\n";
|
||||
out << make_description(sub);
|
||||
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
|
||||
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
|
||||
}
|
||||
out << make_positionals(sub);
|
||||
out << make_groups(sub, mode);
|
||||
out << make_subcommands(sub, mode);
|
||||
}
|
||||
|
||||
// Drop blank spaces
|
||||
tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
|
||||
tmp = tmp.substr(0, tmp.size() - 1);// Remove the final '\n'
|
||||
|
||||
//
|
||||
auto group = sub->get_parent()->get_group();
|
||||
std::vector<const App*> sc_group = sub->get_parent()->get_subcommands(
|
||||
[&group](const App* sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
|
||||
|
||||
if(sc_group.back() != sub) {
|
||||
subc_symbol = tree_line;
|
||||
}
|
||||
|
||||
// Indent all but the first line (the name)
|
||||
return detail::find_and_replace(tmp, "\n", "\n" + subc_symbol + " ") + "\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace CLI
|
||||
|
||||
+1
-1
Submodule libraries/eos-vm updated: 7db4b33fa9...1592261e96
Submodule libraries/libfc/libraries/ff updated: 483970922c...e485effbde
@@ -29,9 +29,9 @@ target_include_directories(secp256k1
|
||||
target_link_libraries(secp256k1 PRIVATE secp256k1-internal)
|
||||
|
||||
install( TARGETS secp256k1
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
add_executable(secp256k1-bench secp256k1/src/bench.c)
|
||||
|
||||
@@ -61,6 +61,11 @@ struct sha3_impl {
|
||||
static constexpr uint8_t rot_constants[number_of_rounds] = {1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44};
|
||||
static constexpr uint8_t pi_lanes[number_of_rounds] = {10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1};
|
||||
|
||||
// Disable "-Wpass-failed=loop-vectorize" for `rho pi` and `chi` loops
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wpass-failed"
|
||||
#endif
|
||||
void update_step()
|
||||
{
|
||||
uint64_t bc[5];
|
||||
@@ -136,6 +141,10 @@ struct sha3_impl {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Re-enable disabled warnings
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
void init() {
|
||||
memset((char *)this, 0, sizeof(*this));
|
||||
@@ -284,4 +293,4 @@ void from_variant(const variant &v, sha3 &bi)
|
||||
else
|
||||
memset(bi.data(), char(0), sizeof(bi));
|
||||
}
|
||||
} // namespace fc
|
||||
} // namespace fc
|
||||
|
||||
@@ -11,7 +11,7 @@ using namespace fc;
|
||||
BOOST_AUTO_TEST_SUITE(variant_estimated_size_suite)
|
||||
BOOST_AUTO_TEST_CASE(null_variant_estimated_size_test)
|
||||
{
|
||||
nullptr_t np;
|
||||
constexpr nullptr_t np=nullptr;
|
||||
|
||||
variant v;
|
||||
variant v_nullptr(np);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
add_library(prometheus-core
|
||||
prometheus-cpp/core/src/check_names.cc
|
||||
prometheus-cpp/core/src/counter.cc
|
||||
prometheus-cpp/core/src/detail/builder.cc
|
||||
prometheus-cpp/core/src/detail/ckms_quantiles.cc
|
||||
prometheus-cpp/core/src/detail/time_window_quantiles.cc
|
||||
prometheus-cpp/core/src/detail/utils.cc
|
||||
prometheus-cpp/core/src/family.cc
|
||||
prometheus-cpp/core/src/gauge.cc
|
||||
prometheus-cpp/core/src/histogram.cc
|
||||
prometheus-cpp/core/src/info.cc
|
||||
prometheus-cpp/core/src/registry.cc
|
||||
prometheus-cpp/core/src/serializer.cc
|
||||
prometheus-cpp/core/src/summary.cc
|
||||
prometheus-cpp/core/src/text_serializer.cc
|
||||
)
|
||||
|
||||
target_include_directories( prometheus-core PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/prometheus-cpp/core/include)
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
# define PROMETHEUS_CPP_CORE_EXPORT
|
||||
# define PROMETHEUS_CPP_CORE_NO_EXPORT
|
||||
@@ -1 +0,0 @@
|
||||
3rdparty
|
||||
@@ -1,10 +0,0 @@
|
||||
build:asan --strip=never
|
||||
build:asan --copt -fsanitize=address
|
||||
build:asan --copt -DADDRESS_SANITIZER
|
||||
build:asan --copt -O0
|
||||
build:asan --copt -fno-omit-frame-pointer
|
||||
build:asan --copt -g
|
||||
build:asan --linkopt -fsanitize=address
|
||||
build:asan --cc_output_directory_tag=asan
|
||||
|
||||
build:ssl --define=with_civetweb_ssl=true
|
||||
@@ -1,2 +0,0 @@
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
@@ -1,61 +0,0 @@
|
||||
name: Bazel CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Bazel on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: macOS-latest
|
||||
bazel_args: "--cxxopt=-std=c++14"
|
||||
- os: ubuntu-latest
|
||||
bazel_args: "--cxxopt=-std=c++14"
|
||||
- os: windows-latest
|
||||
bazel_args: "--cxxopt=/std:c++14"
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Generate German locale on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get remove -y --purge man-db # avoid time-consuming trigger
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y locales
|
||||
sudo locale-gen de_DE.UTF-8 # used by SerializerTest
|
||||
|
||||
- name: Install telegraf on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
|
||||
source /etc/lsb-release
|
||||
echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y telegraf
|
||||
|
||||
- name: Install telegraf on macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install telegraf
|
||||
|
||||
- name: Build with SSL
|
||||
run: bazel build --config=ssl ${{ matrix.bazel_args }} //...
|
||||
|
||||
- name: Test with SSL
|
||||
run: bazel test --config=ssl ${{ matrix.bazel_args }} --test_output=all //...
|
||||
|
||||
- name: Build
|
||||
run: bazel build ${{ matrix.bazel_args }} //...
|
||||
|
||||
- name: Test
|
||||
run: bazel test ${{ matrix.bazel_args }} --test_output=all //...
|
||||
|
||||
- name: Scraping Test
|
||||
if: runner.os != 'Windows'
|
||||
run: bazel test ${{ matrix.bazel_args }} --test_output=all //pull/tests/integration:scrape-test
|
||||
|
||||
- name: Benchmark
|
||||
run: bazel run ${{ matrix.bazel_args }} -c opt //core/benchmarks
|
||||
@@ -1,131 +0,0 @@
|
||||
name: CMake CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: CMake on ${{ matrix.os }} with ${{ matrix.dependencies }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macOS-latest, ubuntu-18.04, windows-2019]
|
||||
dependencies: [submodule, vcpkg]
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: ${{ matrix.dependencies == 'submodule' }}
|
||||
|
||||
- name: Mount vcpkg cache
|
||||
if: matrix.dependencies == 'vcpkg'
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "~/.cache/vcpkg/archives"
|
||||
key: vcpkg-${{ matrix.os }}
|
||||
|
||||
- name: Default to x64-windows vcpkg triplet
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows'
|
||||
run: echo "VCPKG_DEFAULT_TRIPLET=x64-windows" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||
|
||||
- name: Install vcpkg dependencies
|
||||
if: matrix.dependencies == 'vcpkg'
|
||||
run: vcpkg install benchmark civetweb curl[core] gtest zlib
|
||||
|
||||
- name: Generate German locale on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get remove -y --purge man-db # avoid time-consuming trigger
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y locales
|
||||
sudo locale-gen de_DE.UTF-8 # used by SerializerTest
|
||||
|
||||
- name: Install ninja on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get install -y ninja-build
|
||||
|
||||
- name: Install ninja on macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install ninja
|
||||
|
||||
- name: "Configure for Unix with internal dependencies"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }} -B ${{ github.workspace }}/_build
|
||||
|
||||
- name: "Configure for Windows with internal dependencies"
|
||||
if: matrix.dependencies == 'submodule' && runner.os == 'Windows'
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -S ${{ github.workspace }} -B ${{ github.workspace }}/_build
|
||||
|
||||
- name: "Configure for Unix with vcpkg dependencies"
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os != 'Windows'
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_DEBUG_POSTFIX=_d -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }} -B ${{ github.workspace }}/_build
|
||||
|
||||
- name: "Configure for Windows with vcpkg dependencies"
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows'
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -DCMAKE_DEBUG_POSTFIX=_d -S ${{ github.workspace }} -B ${{ github.workspace }}/_build
|
||||
|
||||
- name: "Build Debug"
|
||||
run: cmake --build ${{ github.workspace }}/_build --config Debug
|
||||
|
||||
- name: "Build Release"
|
||||
run: cmake --build ${{ github.workspace }}/_build --config Release
|
||||
|
||||
- name: "Test Debug"
|
||||
run: ctest -C Debug -V -LE Benchmark
|
||||
working-directory: "${{ github.workspace }}/_build"
|
||||
|
||||
- name: "Test Release"
|
||||
run: ctest -C Release -V -LE Benchmark
|
||||
working-directory: "${{ github.workspace }}/_build"
|
||||
|
||||
- name: "Run Benchmark"
|
||||
run: ctest -C Release -V -L Benchmark
|
||||
working-directory: "${{ github.workspace }}/_build"
|
||||
|
||||
- name: "Install Debug"
|
||||
run: cmake --install ${{ github.workspace }}/_build --config Debug
|
||||
|
||||
- name: "Install Release"
|
||||
run: cmake --install ${{ github.workspace }}/_build --config Release
|
||||
|
||||
- name: "Configure CMake import for Unix with internal dependencies"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- name: "Configure CMake import for Windows with internal dependencies"
|
||||
if: matrix.dependencies == 'submodule' && runner.os == 'Windows'
|
||||
run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- name: "Configure CMake import for Unix with vcpkg dependencies"
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os != 'Windows'
|
||||
run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- name: "Configure CMake import for Windows with vcpkg dependencies"
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows'
|
||||
run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- name: "Build CMake import Debug"
|
||||
run: cmake --build ${{ github.workspace }}/_import_cmake --config Debug
|
||||
|
||||
- name: "Build CMake import Release"
|
||||
run: cmake --build ${{ github.workspace }}/_import_cmake --config Release
|
||||
|
||||
- name: "Configure for Unix Shared Libs with internal dependencies"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install_shared -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -GNinja -S ${{ github.workspace }} -B ${{ github.workspace }}/_build_shared
|
||||
|
||||
- name: "Build for Unix Shared Libs"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake --build ${{ github.workspace }}/_build_shared
|
||||
|
||||
- name: "Install for Unix Shared Libs"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake --install ${{ github.workspace }}/_build_shared
|
||||
|
||||
- name: "Configure pkg-config import for Unix"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake -DCMAKE_PREFIX_PATH=${{ github.workspace }}/_install_shared -GNinja -S ${{ github.workspace }}/cmake/project-import-pkgconfig -B ${{ github.workspace }}/_import_pkgconfig
|
||||
|
||||
- name: "Build pkg-config import for Unix"
|
||||
if: matrix.dependencies == 'submodule' && runner.os != 'Windows'
|
||||
run: cmake --build ${{ github.workspace }}/_import_pkgconfig
|
||||
@@ -1,60 +0,0 @@
|
||||
name: Coverage
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Code Coverage
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Mount vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "~/.cache/vcpkg/archives"
|
||||
key: vcpkg-${{ runner.os }}
|
||||
|
||||
- name: Install vcpkg dependencies
|
||||
run: vcpkg install benchmark civetweb curl[core] gtest zlib
|
||||
|
||||
- name: Generate German locale on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get remove -y --purge man-db # avoid time-consuming trigger
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y locales
|
||||
sudo locale-gen de_DE.UTF-8 # used by SerializerTest
|
||||
|
||||
- name: Install ninja on Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get install -y ninja-build
|
||||
|
||||
- name: Install lcov
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
|
||||
- name: "CMake Configure for Unix with vcpkg dependencies"
|
||||
env:
|
||||
CFLAGS: "--coverage"
|
||||
CXXFLAGS: "--coverage"
|
||||
LDFLAGS: "--coverage"
|
||||
run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -GNinja -S ${{ github.workspace }} -B ${{ github.workspace }}/_build
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{ github.workspace }}/_build
|
||||
|
||||
- name: Test
|
||||
run: ctest -V -LE Benchmark
|
||||
working-directory: "${{ github.workspace }}/_build"
|
||||
|
||||
- name: Run lcov
|
||||
run: lcov --capture --directory "${{ github.workspace }}/_build" --output-file coverage.info --no-external --directory "${{ github.workspace }}" --exclude '*/tests/*'
|
||||
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: coverage.info
|
||||
@@ -1,30 +0,0 @@
|
||||
name: Doxygen
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Code Coverage
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install doxygen
|
||||
run: |
|
||||
sudo apt-get remove -y --purge man-db # avoid time-consuming trigger
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y doxygen graphviz
|
||||
|
||||
- name: Generate doxygen
|
||||
run: doxygen
|
||||
working-directory: "${{ github.workspace }}/doc"
|
||||
|
||||
- name: Deploy documentation
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
force_orphan: true
|
||||
publish_dir: ./doc/html
|
||||
@@ -1,55 +0,0 @@
|
||||
name: Linting
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
iwyu:
|
||||
name: Include What You Use
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: debian:sid-slim
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends ca-certificates clang-14 cmake git iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: "CMake Configure"
|
||||
run: cmake -GNinja -DRUN_IWYU=ON -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${GITHUB_WORKSPACE}/_build 2>&1 | tee ${GITHUB_WORKSPACE}/output.txt
|
||||
|
||||
- name: Check build output
|
||||
run: if egrep -q 'should (add|remove) these lines' ${GITHUB_WORKSPACE}/output.txt; then exit 1; fi
|
||||
|
||||
#- name: "CMake Configure"
|
||||
# run: cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build
|
||||
|
||||
#- name: "Run IWYU"
|
||||
# run: iwyu_tool -p ${GITHUB_WORKSPACE}/_build core push pull -- -Xiwyu --mapping_file=${GITHUB_WORKSPACE}/cmake/googletest.imp -Xiwyu --no_fwd_decls 2>&1 | tee ${{ github.workspace }}/output.txt
|
||||
|
||||
format:
|
||||
name: Clang Format
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# clang-format comes pre-installed
|
||||
# https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md
|
||||
#- name: Install dependencies
|
||||
# run: |
|
||||
# sudo apt-get remove -y --purge man-db # avoid time-consuming trigger
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y clang-format-12
|
||||
|
||||
- name: Run clang-format
|
||||
run: find . -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.cxx' -o -name '*.o' -o -name '*.h' -o -name '*.hpp' -o -name '*.hxx' \) -exec clang-format-12 -style=file -i {} \;
|
||||
|
||||
- name: Check for changes
|
||||
run: git diff --exit-code
|
||||
@@ -1,34 +0,0 @@
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
name: Handle Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Upload Release Asset
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
|
||||
- name: Create tarball including submodules
|
||||
shell: bash
|
||||
env:
|
||||
PREFIX: prometheus-cpp-with-submodules
|
||||
run: |
|
||||
git archive --prefix "${PREFIX}/" -o "${PREFIX}.tar" HEAD
|
||||
git submodule foreach --recursive "git archive --prefix=${PREFIX}/\$path/ --output=\$sha1.tar HEAD && tar --concatenate --file=$(pwd)/${PREFIX}.tar \$sha1.tar && rm \$sha1.tar"
|
||||
gzip "${PREFIX}.tar"
|
||||
|
||||
# using the official actions/upload-release-asset action would be preferred but is blocked by
|
||||
# https://github.com/actions/upload-release-asset/pull/41
|
||||
- name: Upload the artifacts
|
||||
uses: skx/github-action-publish-binaries@75ce5546020fc1848da842f40240f9fa03e7a3a8 # release-0.14
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: prometheus-cpp-with-submodules.tar.gz
|
||||
@@ -1,7 +0,0 @@
|
||||
/bazel-*
|
||||
cmake-build-*/
|
||||
_*/
|
||||
.idea/
|
||||
doc/html/
|
||||
.vscode
|
||||
build
|
||||
@@ -1,6 +0,0 @@
|
||||
[submodule "googletest"]
|
||||
path = 3rdparty/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
[submodule "civetweb"]
|
||||
path = 3rdparty/civetweb
|
||||
url = https://github.com/civetweb/civetweb.git
|
||||
@@ -1,11 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
values = {"cpu": "x64_windows"},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows_msvc",
|
||||
values = {"cpu": "x64_windows_msvc"},
|
||||
)
|
||||
@@ -1,193 +0,0 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
endif()
|
||||
|
||||
project(prometheus-cpp
|
||||
VERSION 1.1.0
|
||||
DESCRIPTION "Prometheus Client Library for Modern C++"
|
||||
HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp"
|
||||
)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build libraries as shared ones" OFF)
|
||||
option(ENABLE_PULL "Build prometheus-cpp pull library" ON)
|
||||
option(ENABLE_PUSH "Build prometheus-cpp push library" ON)
|
||||
option(ENABLE_COMPRESSION "Enable gzip compression" ON)
|
||||
option(ENABLE_TESTING "Build tests" ON)
|
||||
option(USE_THIRDPARTY_LIBRARIES "Use 3rdParty submodules" ON)
|
||||
option(THIRDPARTY_CIVETWEB_WITH_SSL "Enable SSL support for embedded civetweb source code")
|
||||
option(OVERRIDE_CXX_STANDARD_FLAGS "Force building with -std=c++11 even if the CXXLFAGS are configured differently" ON)
|
||||
option(GENERATE_PKGCONFIG "Generate and install pkg-config files" ${UNIX})
|
||||
option(RUN_IWYU "Run include-what-you-use" OFF)
|
||||
|
||||
if(OVERRIDE_CXX_STANDARD_FLAGS)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_EXTENSIONS Off)
|
||||
endif()
|
||||
|
||||
# Set default directory permissions until
|
||||
# https://gitlab.kitware.com/cmake/cmake/issues/15163
|
||||
# is fixed
|
||||
set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
|
||||
OWNER_READ
|
||||
OWNER_WRITE
|
||||
OWNER_EXECUTE
|
||||
GROUP_READ
|
||||
GROUP_EXECUTE
|
||||
WORLD_READ
|
||||
WORLD_EXECUTE)
|
||||
|
||||
# Put DLLs and binaries into same directory
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
# Hide things by default for shared libraries
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads)
|
||||
|
||||
# include-what-you-use
|
||||
|
||||
if(RUN_IWYU)
|
||||
find_program(IWYU_EXECUTABLE NAMES include-what-you-use iwyu)
|
||||
if(NOT IWYU_EXECUTABLE)
|
||||
message(FATAL_ERROR "Include-what-you-use not found")
|
||||
endif()
|
||||
|
||||
set(IWYU_ARGS
|
||||
"${IWYU_EXECUTABLE}"
|
||||
"-Xiwyu" "--no_fwd_decls"
|
||||
"-Xiwyu" "--mapping_file=${CMAKE_CURRENT_SOURCE_DIR}/cmake/googletest.imp"
|
||||
)
|
||||
|
||||
set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_ARGS})
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_ARGS})
|
||||
endif()
|
||||
|
||||
# check for required libatomic
|
||||
|
||||
include(CheckAtomic)
|
||||
|
||||
if(ENABLE_TESTING)
|
||||
if(USE_THIRDPARTY_LIBRARIES)
|
||||
find_package(googlemock-3rdparty CONFIG REQUIRED)
|
||||
else()
|
||||
find_package(GTest 1.8.1 CONFIG REQUIRED)
|
||||
endif()
|
||||
find_package(benchmark CONFIG)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
# build flags for CI system
|
||||
|
||||
if(ENABLE_WARNINGS_AS_ERRORS AND NOT MSVC)
|
||||
add_compile_options(
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Werror>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Wall>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Wextra>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-pedantic-errors>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-Werror>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-Wall>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-pedantic-errors>
|
||||
)
|
||||
endif()
|
||||
|
||||
# pkgconfig
|
||||
|
||||
if(GENERATE_PKGCONFIG)
|
||||
# see https://github.com/jupp0r/prometheus-cpp/issues/587
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# prometheus-cpp
|
||||
|
||||
add_subdirectory(core)
|
||||
|
||||
if(ENABLE_PULL)
|
||||
add_subdirectory(pull)
|
||||
endif()
|
||||
|
||||
if(ENABLE_PUSH)
|
||||
add_subdirectory(push)
|
||||
endif()
|
||||
|
||||
# install
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE ${PROJECT_NAME}-targets.cmake
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in"
|
||||
${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
# packaging
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(CPACK_PACKAGE_CONTACT "prometheus-cpp@@noreply.github.com")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
|
||||
set(CPACK_PACKAGE_RELOCATABLE OFF)
|
||||
set(CPACK_PACKAGE_VENDOR "The prometheus-cpp authors")
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.12")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||
endif()
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
||||
|
||||
set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)
|
||||
set(CPACK_RPM_FILE_NAME RPM-DEFAULT)
|
||||
|
||||
include(CPack)
|
||||
endif()
|
||||
|
||||
# summary
|
||||
|
||||
include(FeatureSummary)
|
||||
add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics")
|
||||
add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway")
|
||||
add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics")
|
||||
add_feature_info("pkg-config" "${GENERATE_PKGCONFIG}" "generate pkg-config files")
|
||||
add_feature_info("IYWU" "${RUN_IWYU}" "include-what-you-use")
|
||||
feature_summary(WHAT ALL)
|
||||
@@ -1,25 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2021 Jupp Mueller
|
||||
Copyright (c) 2017-2022 Gregor Jasny
|
||||
|
||||
And many contributors, see
|
||||
https://github.com/jupp0r/prometheus-cpp/graphs/contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,382 +0,0 @@
|
||||
# Prometheus Client Library for Modern C++
|
||||
|
||||
[](https://github.com/jupp0r/prometheus-cpp/actions?workflow=Continuous+Integration)
|
||||
[](https://travis-ci.org/jupp0r/prometheus-cpp)
|
||||
[](https://coveralls.io/github/jupp0r/prometheus-cpp?branch=master)
|
||||
[](https://scan.coverity.com/projects/jupp0r-prometheus-cpp)
|
||||
|
||||
This library aims to enable
|
||||
[Metrics-Driven Development](https://sookocheff.com/post/mdd/mdd/) for
|
||||
C++ services. It implements the
|
||||
[Prometheus Data Model](https://prometheus.io/docs/concepts/data_model/),
|
||||
a powerful abstraction on which to collect and expose metrics. We
|
||||
offer the possibility for metrics to be collected by Prometheus, but
|
||||
other push/pull collections can be added as plugins.
|
||||
|
||||
## Usage
|
||||
|
||||
See https://jupp0r.github.io/prometheus-cpp for more detailed interface documentation.
|
||||
|
||||
``` c++
|
||||
#include <prometheus/counter.h>
|
||||
#include <prometheus/exposer.h>
|
||||
#include <prometheus/registry.h>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
int main() {
|
||||
using namespace prometheus;
|
||||
|
||||
// create an http server running on port 8080
|
||||
Exposer exposer{"127.0.0.1:8080"};
|
||||
|
||||
// create a metrics registry
|
||||
// @note it's the users responsibility to keep the object alive
|
||||
auto registry = std::make_shared<Registry>();
|
||||
|
||||
// add a new counter family to the registry (families combine values with the
|
||||
// same name, but distinct label dimensions)
|
||||
//
|
||||
// @note please follow the metric-naming best-practices:
|
||||
// https://prometheus.io/docs/practices/naming/
|
||||
auto& packet_counter = BuildCounter()
|
||||
.Name("observed_packets_total")
|
||||
.Help("Number of observed packets")
|
||||
.Register(*registry);
|
||||
|
||||
// add and remember dimensional data, incrementing those is very cheap
|
||||
auto& tcp_rx_counter =
|
||||
packet_counter.Add({{"protocol", "tcp"}, {"direction", "rx"}});
|
||||
auto& tcp_tx_counter =
|
||||
packet_counter.Add({{"protocol", "tcp"}, {"direction", "tx"}});
|
||||
auto& udp_rx_counter =
|
||||
packet_counter.Add({{"protocol", "udp"}, {"direction", "rx"}});
|
||||
auto& udp_tx_counter =
|
||||
packet_counter.Add({{"protocol", "udp"}, {"direction", "tx"}});
|
||||
|
||||
// add a counter whose dimensional data is not known at compile time
|
||||
// nevertheless dimensional values should only occur in low cardinality:
|
||||
// https://prometheus.io/docs/practices/naming/#labels
|
||||
auto& http_requests_counter = BuildCounter()
|
||||
.Name("http_requests_total")
|
||||
.Help("Number of HTTP requests")
|
||||
.Register(*registry);
|
||||
|
||||
// ask the exposer to scrape the registry on incoming HTTP requests
|
||||
exposer.RegisterCollectable(registry);
|
||||
|
||||
for (;;) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
const auto random_value = std::rand();
|
||||
|
||||
if (random_value & 1) tcp_rx_counter.Increment();
|
||||
if (random_value & 2) tcp_tx_counter.Increment();
|
||||
if (random_value & 4) udp_rx_counter.Increment();
|
||||
if (random_value & 8) udp_tx_counter.Increment();
|
||||
|
||||
const std::array<std::string, 4> methods = {"GET", "PUT", "POST", "HEAD"};
|
||||
auto method = methods.at(random_value % methods.size());
|
||||
// dynamically calling Family<T>.Add() works but is slow and should be
|
||||
// avoided
|
||||
http_requests_counter.Add({{"method", method}}).Increment();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
Using `prometheus-cpp` requires a C++11 compliant compiler. It has been successfully tested with GNU GCC 7.4 on Ubuntu Bionic (18.04) and Visual Studio 2017 (but Visual Studio 2015 should work, too).
|
||||
|
||||
## Building
|
||||
|
||||
There are two supported ways to build
|
||||
`prometheus-cpp` - [CMake](https://cmake.org)
|
||||
and [bazel](https://bazel.io). Both are tested in CI and should work
|
||||
on master and for all releases.
|
||||
|
||||
In case these instructions don't work for you, looking at
|
||||
the [GitHub Workflows](.github/workflows) might help.
|
||||
|
||||
### via CMake
|
||||
|
||||
For CMake builds don't forget to fetch the submodules first. Please note that
|
||||
[zlib](https://zlib.net/) and [libcurl](https://curl.se/) are not provided by
|
||||
the included submodules. In the example below their usage is disabled.
|
||||
|
||||
Then build as usual.
|
||||
|
||||
``` shell
|
||||
# fetch third-party dependencies
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
mkdir _build
|
||||
cd _build
|
||||
|
||||
# run cmake
|
||||
cmake .. -DBUILD_SHARED_LIBS=ON -DENABLE_PUSH=OFF -DENABLE_COMPRESSION=OFF
|
||||
|
||||
# build
|
||||
cmake --build . --parallel 4
|
||||
|
||||
# run tests
|
||||
ctest -V
|
||||
|
||||
# install the libraries and headers
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
### via Bazel
|
||||
|
||||
Install [bazel](https://www.bazel.io). Bazel makes it easy to add
|
||||
this repo to your project as a dependency. Just add the following
|
||||
to your `WORKSPACE`:
|
||||
|
||||
```python
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
|
||||
http_archive(
|
||||
name = "com_github_jupp0r_prometheus_cpp",
|
||||
strip_prefix = "prometheus-cpp-master",
|
||||
urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"],
|
||||
)
|
||||
|
||||
load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories")
|
||||
|
||||
prometheus_cpp_repositories()
|
||||
```
|
||||
|
||||
Then, you can reference this library in your own `BUILD` file, as
|
||||
demonstrated with the sample server included in this repository:
|
||||
|
||||
```python
|
||||
cc_binary(
|
||||
name = "sample_server",
|
||||
srcs = ["sample_server.cc"],
|
||||
deps = ["@com_github_jupp0r_prometheus_cpp//pull"],
|
||||
)
|
||||
```
|
||||
|
||||
When you call `prometheus_cpp_repositories()` in your `WORKSPACE` file,
|
||||
you load the following dependencies, if they do not exist yet, into your project:
|
||||
|
||||
* `civetweb` for [Civetweb](https://github.com/civetweb/civetweb)
|
||||
* `com_google_googletest` for [Google Test](https://github.com/google/googletest)
|
||||
* `com_github_google_benchmark` for [Google Benchmark](https://github.com/google/benchmark)
|
||||
* `com_github_curl` for [curl](https://curl.haxx.se/)
|
||||
* `net_zlib_zlib` for [zlib](http://www.zlib.net/)
|
||||
|
||||
The list of dependencies is also available from file [repositories.bzl](bazel/repositories.bzl).
|
||||
|
||||
## Packaging
|
||||
|
||||
By configuring CPack you can generate an installer like a
|
||||
Debian package (.deb) or RPM (.rpm) for the static or dynamic
|
||||
libraries so they can be easily installed on
|
||||
other systems.
|
||||
|
||||
Please refer to the [CPack](https://cmake.org/cmake/help/latest/module/CPack.html)
|
||||
documentation for all available generators and their
|
||||
configuration options.
|
||||
|
||||
To generate a Debian package you could follow these steps:
|
||||
|
||||
``` shell
|
||||
# fetch third-party dependencies
|
||||
git submodule update --init
|
||||
|
||||
# run cmake
|
||||
cmake -B_build -DCPACK_GENERATOR=DEB -DBUILD_SHARED_LIBS=ON # or OFF for static libraries
|
||||
|
||||
# build and package
|
||||
cmake --build _build --target package --parallel $(nproc)
|
||||
```
|
||||
|
||||
This will place an appropriately named .deb in the
|
||||
`_build` folder. To build a RPM package set the `CPACK_GENERATOR`
|
||||
variable to `RPM`.
|
||||
|
||||
## Consuming the installed project
|
||||
|
||||
### CMake
|
||||
|
||||
Consuming prometheus-cpp via CMake is the preferred way because all the dependencies
|
||||
between the three prometheus-cpp libraries are handled correctly.
|
||||
|
||||
The `cmake/project-import` directory contains an
|
||||
example project and minimal [CMakeLists.txt](cmake/project-import-cmake/CMakeLists.txt).
|
||||
|
||||
### vcpkg
|
||||
|
||||
The [vcpkg](https://github.com/microsoft/vcpkg) package manager contains a
|
||||
prometheus-cpp port which has been tested on Linux, macOS, and Windows.
|
||||
|
||||
### Conan
|
||||
|
||||
[Conan](https://conan.io/) package manager contains prometheus-cpp package as well
|
||||
in [ConanCenter](https://conan.io/center/prometheus-cpp) repository
|
||||
|
||||
### Plain Makefiles
|
||||
|
||||
When manually linking prometheus-cpp the library order matters. The needed
|
||||
libraries depend on the individual use case but the following should work for the pull metrics approach:
|
||||
|
||||
```
|
||||
-lprometheus-cpp-pull -lprometheus-cpp-core -lz
|
||||
```
|
||||
|
||||
For the push-workflow please try:
|
||||
|
||||
```
|
||||
-lprometheus-cpp-push -lprometheus-cpp-core -lcurl -lz
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Please adhere to the [Google C++ Style
|
||||
Guide](https://google.github.io/styleguide/cppguide.html). Make sure
|
||||
to clang-format your patches before opening a PR. Also make sure to
|
||||
adhere to [these commit message
|
||||
guidelines](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
You can check out this repo and build the library using
|
||||
``` bash
|
||||
bazel build //... # build everything
|
||||
bazel build //core //pull # build just the libraries
|
||||
```
|
||||
|
||||
Run the unit tests using
|
||||
```
|
||||
bazel test //...
|
||||
```
|
||||
|
||||
There is also an integration test that
|
||||
uses [telegraf](https://github.com/influxdata/telegraf) to scrape a
|
||||
sample server. With telegraf installed, it can be run using
|
||||
```
|
||||
bazel test //pull/tests/integration:scrape-test
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
There's a benchmark suite you can run:
|
||||
|
||||
```
|
||||
bazel run -c opt //core/benchmarks
|
||||
|
||||
INFO: Analysed target //core/benchmarks:benchmarks (0 packages loaded, 0 targets configured).
|
||||
INFO: Found 1 target...
|
||||
Target //core/benchmarks:benchmarks up-to-date:
|
||||
bazel-bin/core/benchmarks/benchmarks
|
||||
INFO: Elapsed time: 0.356s, Critical Path: 0.01s, Remote (0.00% of the time): [queue: 0.00%, setup: 0.00%, process: 0.00%]
|
||||
INFO: 0 processes.
|
||||
INFO: Build completed successfully, 1 total action
|
||||
INFO: Build completed successfully, 1 total action
|
||||
2018-11-30 15:13:14
|
||||
Run on (4 X 2200 MHz CPU s)
|
||||
CPU Caches:
|
||||
L1 Data 32K (x2)
|
||||
L1 Instruction 32K (x2)
|
||||
L2 Unified 262K (x2)
|
||||
L3 Unified 4194K (x1)
|
||||
-----------------------------------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
-----------------------------------------------------------------------------------
|
||||
BM_Counter_Increment 13 ns 12 ns 55616469
|
||||
BM_Counter_Collect 7 ns 7 ns 99823170
|
||||
BM_Gauge_Increment 12 ns 12 ns 51511873
|
||||
BM_Gauge_Decrement 12 ns 12 ns 56831098
|
||||
BM_Gauge_SetToCurrentTime 184 ns 183 ns 3928964
|
||||
BM_Gauge_Collect 6 ns 6 ns 117223478
|
||||
BM_Histogram_Observe/0 134 ns 124 ns 5665310
|
||||
BM_Histogram_Observe/1 122 ns 120 ns 5937185
|
||||
BM_Histogram_Observe/8 137 ns 135 ns 4652863
|
||||
BM_Histogram_Observe/64 143 ns 143 ns 4835957
|
||||
BM_Histogram_Observe/512 259 ns 257 ns 2334750
|
||||
BM_Histogram_Observe/4096 1545 ns 1393 ns 620754
|
||||
BM_Histogram_Collect/0 103 ns 102 ns 5654829
|
||||
BM_Histogram_Collect/1 100 ns 100 ns 7015153
|
||||
BM_Histogram_Collect/8 608 ns 601 ns 1149652
|
||||
BM_Histogram_Collect/64 1438 ns 1427 ns 515236
|
||||
BM_Histogram_Collect/512 5178 ns 5159 ns 114619
|
||||
BM_Histogram_Collect/4096 33527 ns 33280 ns 20785
|
||||
BM_Registry_CreateFamily 320 ns 316 ns 2021567
|
||||
BM_Registry_CreateCounter/0 128 ns 128 ns 5487140
|
||||
BM_Registry_CreateCounter/1 2066 ns 2058 ns 386002
|
||||
BM_Registry_CreateCounter/8 7672 ns 7634 ns 91328
|
||||
BM_Registry_CreateCounter/64 63270 ns 62761 ns 10780
|
||||
BM_Registry_CreateCounter/512 560714 ns 558328 ns 1176
|
||||
BM_Registry_CreateCounter/4096 18672798 ns 18383000 ns 35
|
||||
BM_Summary_Observe/0/iterations:262144 9351 ns 9305 ns 262144
|
||||
BM_Summary_Observe/1/iterations:262144 9242 ns 9169 ns 262144
|
||||
BM_Summary_Observe/8/iterations:262144 14344 ns 14195 ns 262144
|
||||
BM_Summary_Observe/64/iterations:262144 19176 ns 18950 ns 262144
|
||||
BM_Summary_Collect/0/0 31 ns 30 ns 24873766
|
||||
BM_Summary_Collect/1/0 166 ns 166 ns 4266706
|
||||
BM_Summary_Collect/8/0 1040 ns 1036 ns 660527
|
||||
BM_Summary_Collect/64/0 4529 ns 4489 ns 155600
|
||||
BM_Summary_Collect/0/1 28 ns 28 ns 24866697
|
||||
BM_Summary_Collect/1/1 190 ns 188 ns 3930354
|
||||
BM_Summary_Collect/8/1 1372 ns 1355 ns 535779
|
||||
BM_Summary_Collect/64/1 9901 ns 9822 ns 64632
|
||||
BM_Summary_Collect/0/8 29 ns 29 ns 24922651
|
||||
BM_Summary_Collect/1/8 217 ns 215 ns 3278381
|
||||
BM_Summary_Collect/8/8 2275 ns 2256 ns 282503
|
||||
BM_Summary_Collect/64/8 56790 ns 55804 ns 13878
|
||||
BM_Summary_Collect/0/64 32 ns 31 ns 22548350
|
||||
BM_Summary_Collect/1/64 395 ns 389 ns 1817073
|
||||
BM_Summary_Collect/8/64 10187 ns 10064 ns 71928
|
||||
BM_Summary_Collect/64/64 374835 ns 373560 ns 1812
|
||||
BM_Summary_Collect/0/512 28 ns 28 ns 25234228
|
||||
BM_Summary_Collect/1/512 1710 ns 1639 ns 802285
|
||||
BM_Summary_Collect/8/512 50355 ns 49335 ns 15975
|
||||
BM_Summary_Collect/64/512 2520972 ns 2493417 ns 295
|
||||
BM_Summary_Collect/0/4096 31 ns 31 ns 24059034
|
||||
BM_Summary_Collect/1/4096 2719 ns 2698 ns 286186
|
||||
BM_Summary_Collect/8/4096 121689 ns 119995 ns 5647
|
||||
BM_Summary_Collect/64/4096 5660131 ns 5587634 ns 134
|
||||
BM_Summary_Collect/0/32768 29 ns 29 ns 22217567
|
||||
BM_Summary_Collect/1/32768 4344 ns 4294 ns 138135
|
||||
BM_Summary_Collect/8/32768 331563 ns 326403 ns 2017
|
||||
BM_Summary_Collect/64/32768 16363553 ns 16038182 ns 44
|
||||
BM_Summary_Collect/0/262144 27 ns 27 ns 23923036
|
||||
BM_Summary_Collect/1/262144 10457 ns 10332 ns 67690
|
||||
BM_Summary_Collect/8/262144 930434 ns 869234 ns 792
|
||||
BM_Summary_Collect/64/262144 39217069 ns 39054846 ns 13
|
||||
BM_Summary_Observe_Common/iterations:262144 5587 ns 5557 ns 262144
|
||||
BM_Summary_Collect_Common/0 676 ns 673 ns 1054630
|
||||
BM_Summary_Collect_Common/1 709 ns 705 ns 990659
|
||||
BM_Summary_Collect_Common/8 1030 ns 1025 ns 685649
|
||||
BM_Summary_Collect_Common/64 2066 ns 2055 ns 339969
|
||||
BM_Summary_Collect_Common/512 5754 ns 5248 ns 156895
|
||||
BM_Summary_Collect_Common/4096 23894 ns 23292 ns 31096
|
||||
BM_Summary_Collect_Common/32768 49831 ns 49292 ns 13492
|
||||
BM_Summary_Collect_Common/262144 128723 ns 126987 ns 5579
|
||||
```
|
||||
|
||||
## Project Status
|
||||
Stable and used in production.
|
||||
|
||||
Parts of the library are instrumented by itself
|
||||
(bytes scraped, number of scrapes, scrape request latencies). There
|
||||
is a working [example](pull/tests/integration/sample_server.cc) that's
|
||||
scraped by telegraf as part of integration tests.
|
||||
|
||||
## FAQ
|
||||
|
||||
### What scrape formats do you support
|
||||
|
||||
Only the [Prometheus Text Exposition
|
||||
Format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-details).
|
||||
Support for the protobuf format was removed because it's been removed
|
||||
from Prometheus 2.0.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -1,5 +0,0 @@
|
||||
workspace(name = "com_github_jupp0r_prometheus_cpp")
|
||||
|
||||
load("//bazel:repositories.bzl", "prometheus_cpp_repositories")
|
||||
|
||||
prometheus_cpp_repositories()
|
||||
@@ -1,7 +0,0 @@
|
||||
exports_files(
|
||||
glob([
|
||||
"*.BUILD",
|
||||
"*.tpl",
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -1,103 +0,0 @@
|
||||
licenses(["notice"]) # MIT license
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:osx",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:windows",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "with_ssl",
|
||||
define_values = {
|
||||
"with_civetweb_ssl": "true",
|
||||
},
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
COPTS = [
|
||||
"-DUSE_IPV6",
|
||||
"-DNDEBUG",
|
||||
"-DNO_CGI",
|
||||
"-DNO_CACHING",
|
||||
"-DNO_FILES",
|
||||
"-UDEBUG",
|
||||
] + select({
|
||||
":with_ssl": [
|
||||
"-DOPENSSL_API_1_1",
|
||||
"-DNO_SSL_DL",
|
||||
],
|
||||
"@//conditions:default": [
|
||||
"-DNO_SSL",
|
||||
],
|
||||
})
|
||||
|
||||
DEPS = select({
|
||||
":with_ssl": [
|
||||
"@boringssl//:crypto",
|
||||
"@boringssl//:ssl",
|
||||
],
|
||||
"@//conditions:default": [],
|
||||
})
|
||||
|
||||
cc_library(
|
||||
name = "libcivetweb",
|
||||
srcs = [
|
||||
"src/civetweb.c",
|
||||
"src/response.inl",
|
||||
],
|
||||
hdrs = [
|
||||
"include/civetweb.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lpthread"],
|
||||
}) + select({
|
||||
":osx": [],
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lrt"],
|
||||
}),
|
||||
textual_hdrs = [
|
||||
"src/md5.inl",
|
||||
"src/handle_form.inl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = DEPS,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "civetweb",
|
||||
srcs = [
|
||||
"src/CivetServer.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/CivetServer.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lpthread"],
|
||||
}) + select({
|
||||
":osx": [],
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lrt"],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":libcivetweb",
|
||||
],
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
# Copyright 2017, OpenCensus Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# copied from: https://github.com/census-instrumentation/opencensus-cpp/blob/master/WORKSPACE
|
||||
|
||||
licenses(["notice"]) # MIT/X derivative license
|
||||
|
||||
load("@com_github_jupp0r_prometheus_cpp//bazel:curl.bzl", "CURL_COPTS")
|
||||
|
||||
package(features = ["no_copts_tokenization"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:windows",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:osx",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "curl",
|
||||
srcs = glob([
|
||||
"lib/**/*.c",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"include/curl/*.h",
|
||||
"lib/**/*.h",
|
||||
]),
|
||||
copts = CURL_COPTS + [
|
||||
'-DOS="os"',
|
||||
],
|
||||
defines = ["CURL_STATICLIB"],
|
||||
includes = [
|
||||
"include/",
|
||||
"lib/",
|
||||
],
|
||||
linkopts = select({
|
||||
"//:windows": [
|
||||
"-DEFAULTLIB:ws2_32.lib",
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
"-DEFAULTLIB:crypt32.lib",
|
||||
"-DEFAULTLIB:Normaliz.lib",
|
||||
],
|
||||
"//:osx": [
|
||||
"-framework SystemConfiguration",
|
||||
"-lpthread",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"-lpthread",
|
||||
],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -1,201 +0,0 @@
|
||||
# Copyright 2018, OpenCensus Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Compiler options for building libcurl.
|
||||
# copied from: https://github.com/census-instrumentation/opencensus-cpp/blob/master/opencensus/curl.bzl
|
||||
|
||||
BASE_CURL_COPTS = [
|
||||
# Disable everything else except HTTP protocol.
|
||||
"-DHTTP_ONLY=1",
|
||||
"-DENABLE_IPV6=1",
|
||||
"-DGETHOSTNAME_TYPE_ARG2=size_t",
|
||||
"-DGETSERVBYPORT_R_ARGS=6",
|
||||
"-DGETSERVBYPORT_R_BUFSIZE=4096",
|
||||
"-DHAVE_ALARM=1",
|
||||
"-DHAVE_ALLOCA_H=1",
|
||||
"-DHAVE_ARPA_INET_H=1",
|
||||
"-DHAVE_ARPA_TFTP_H=1",
|
||||
"-DHAVE_ASSERT_H=1",
|
||||
"-DHAVE_BASENAME=1",
|
||||
"-DHAVE_BOOL_T=1",
|
||||
"-DHAVE_CLOCK_GETTIME_MONOTONIC=1",
|
||||
"-DHAVE_CONNECT=1",
|
||||
"-DHAVE_DLFCN_H=1",
|
||||
"-DHAVE_ENGINE_LOAD_BUILTIN_ENGINES=1",
|
||||
"-DHAVE_ERRNO_H=1",
|
||||
"-DHAVE_FCNTL=1",
|
||||
"-DHAVE_FCNTL_H=1",
|
||||
"-DHAVE_FCNTL_O_NONBLOCK=1",
|
||||
"-DHAVE_FDOPEN=1",
|
||||
"-DHAVE_FREEADDRINFO=1",
|
||||
"-DHAVE_FREEIFADDRS=1",
|
||||
"-DHAVE_FSETXATTR=1",
|
||||
"-DHAVE_FSETXATTR_5=1",
|
||||
"-DHAVE_FTRUNCATE=1",
|
||||
"-DHAVE_GAI_STRERROR=1",
|
||||
"-DHAVE_GETADDRINFO=1",
|
||||
"-DHAVE_GETADDRINFO_THREADSAFE=1",
|
||||
"-DHAVE_GETEUID=1",
|
||||
"-DHAVE_GETHOSTBYADDR=1",
|
||||
"-DHAVE_GETHOSTBYADDR_R=1",
|
||||
"-DHAVE_GETHOSTBYADDR_R_8=1",
|
||||
"-DHAVE_GETHOSTBYNAME=1",
|
||||
"-DHAVE_GETHOSTBYNAME_R=1",
|
||||
"-DHAVE_GETHOSTBYNAME_R_6=1",
|
||||
"-DHAVE_GETHOSTNAME=1",
|
||||
"-DHAVE_GETIFADDRS=1",
|
||||
"-DHAVE_GETPPID=1",
|
||||
"-DHAVE_GETPWUID=1",
|
||||
"-DHAVE_GETPWUID_R=1",
|
||||
"-DHAVE_GETRLIMIT=1",
|
||||
"-DHAVE_GETSERVBYPORT_R=1",
|
||||
"-DHAVE_GETTIMEOFDAY=1",
|
||||
"-DHAVE_GMTIME_R=1",
|
||||
"-DHAVE_IFADDRS_H=1",
|
||||
"-DHAVE_IF_NAMETOINDEX=1",
|
||||
"-DHAVE_INET_NTOP=1",
|
||||
"-DHAVE_INET_PTON=1",
|
||||
"-DHAVE_INTTYPES_H=1",
|
||||
"-DHAVE_IOCTL=1",
|
||||
"-DHAVE_IOCTL_FIONBIO=1",
|
||||
"-DHAVE_IOCTL_SIOCGIFADDR=1",
|
||||
"-DHAVE_LIBGEN_H=1",
|
||||
"-DHAVE_LL=1",
|
||||
"-DHAVE_LOCALE_H=1",
|
||||
"-DHAVE_LOCALTIME_R=1",
|
||||
"-DHAVE_LONGLONG=1",
|
||||
"-DHAVE_MALLOC_H=1",
|
||||
"-DHAVE_MEMORY_H=1",
|
||||
"-DHAVE_NETDB_H=1",
|
||||
"-DHAVE_NETINET_IN_H=1",
|
||||
"-DHAVE_NETINET_TCP_H=1",
|
||||
"-DHAVE_NET_IF_H=1",
|
||||
"-DHAVE_PIPE=1",
|
||||
"-DHAVE_POLL=1",
|
||||
"-DHAVE_POLL_FINE=1",
|
||||
"-DHAVE_POLL_H=1",
|
||||
"-DHAVE_POSIX_STRERROR_R=1",
|
||||
"-DHAVE_PTHREAD_H=1",
|
||||
"-DHAVE_PWD_H=1",
|
||||
"-DHAVE_RECV=1",
|
||||
"-DHAVE_SA_FAMILY_T=1",
|
||||
"-DHAVE_SELECT=1",
|
||||
"-DHAVE_SEND=1",
|
||||
"-DHAVE_SETJMP_H=1",
|
||||
"-DHAVE_SETLOCALE=1",
|
||||
"-DHAVE_SETRLIMIT=1",
|
||||
"-DHAVE_SETSOCKOPT=1",
|
||||
"-DHAVE_SGTTY_H=1",
|
||||
"-DHAVE_SIGACTION=1",
|
||||
"-DHAVE_SIGINTERRUPT=1",
|
||||
"-DHAVE_SIGNAL=1",
|
||||
"-DHAVE_SIGNAL_H=1",
|
||||
"-DHAVE_SIGSETJMP=1",
|
||||
"-DHAVE_SIG_ATOMIC_T=1",
|
||||
"-DHAVE_SOCKADDR_IN6_SIN6_SCOPE_ID=1",
|
||||
"-DHAVE_SOCKET=1",
|
||||
"-DHAVE_SOCKETPAIR=1",
|
||||
"-DHAVE_STDBOOL_H=1",
|
||||
"-DHAVE_STDINT_H=1",
|
||||
"-DHAVE_STDIO_H=1",
|
||||
"-DHAVE_STDLIB_H=1",
|
||||
"-DHAVE_STRCASECMP=1",
|
||||
"-DHAVE_STRDUP=1",
|
||||
"-DHAVE_STRERROR_R=1",
|
||||
"-DHAVE_STRINGS_H=1",
|
||||
"-DHAVE_STRING_H=1",
|
||||
"-DHAVE_STRNCASECMP=1",
|
||||
"-DHAVE_STRSTR=1",
|
||||
"-DHAVE_STRTOK_R=1",
|
||||
"-DHAVE_STRTOLL=1",
|
||||
"-DHAVE_STRUCT_SOCKADDR_STORAGE=1",
|
||||
"-DHAVE_STRUCT_TIMEVAL=1",
|
||||
"-DHAVE_SYS_IOCTL_H=1",
|
||||
"-DHAVE_SYS_PARAM_H=1",
|
||||
"-DHAVE_SYS_POLL_H=1",
|
||||
"-DHAVE_SYS_RESOURCE_H=1",
|
||||
"-DHAVE_SYS_SELECT_H=1",
|
||||
"-DHAVE_SYS_SOCKET_H=1",
|
||||
"-DHAVE_SYS_STAT_H=1",
|
||||
"-DHAVE_SYS_TIME_H=1",
|
||||
"-DHAVE_SYS_TYPES_H=1",
|
||||
"-DHAVE_SYS_UIO_H=1",
|
||||
"-DHAVE_SYS_UN_H=1",
|
||||
"-DHAVE_SYS_WAIT_H=1",
|
||||
"-DHAVE_SYS_XATTR_H=1",
|
||||
"-DHAVE_TERMIOS_H=1",
|
||||
"-DHAVE_TERMIO_H=1",
|
||||
"-DHAVE_TIME_H=1",
|
||||
"-DHAVE_UNISTD_H=1",
|
||||
"-DHAVE_UTIME=1",
|
||||
"-DHAVE_UTIMES=1",
|
||||
"-DHAVE_UTIME_H=1",
|
||||
"-DHAVE_VARIADIC_MACROS_C99=1",
|
||||
"-DHAVE_VARIADIC_MACROS_GCC=1",
|
||||
"-DHAVE_WRITABLE_ARGV=1",
|
||||
"-DHAVE_WRITEV=1",
|
||||
"-DRECV_TYPE_ARG1=int",
|
||||
"-DRECV_TYPE_ARG2=void*",
|
||||
"-DRECV_TYPE_ARG3=size_t",
|
||||
"-DRECV_TYPE_ARG4=int",
|
||||
"-DRECV_TYPE_RETV=ssize_t",
|
||||
"-DSELECT_QUAL_ARG5=",
|
||||
"-DSELECT_TYPE_ARG1=int",
|
||||
"-DSELECT_TYPE_ARG234=fd_set*",
|
||||
"-DSELECT_TYPE_RETV=int",
|
||||
"-DSEND_QUAL_ARG2=const",
|
||||
"-DSEND_TYPE_ARG1=int",
|
||||
"-DSEND_TYPE_ARG2=void*",
|
||||
"-DSEND_TYPE_ARG3=size_t",
|
||||
"-DSEND_TYPE_ARG4=int",
|
||||
"-DSEND_TYPE_RETV=ssize_t",
|
||||
"-DSIZEOF_CURL_OFF_T=8",
|
||||
"-DSIZEOF_INT=4",
|
||||
"-DSIZEOF_LONG=8",
|
||||
"-DSIZEOF_OFF_T=8",
|
||||
"-DSIZEOF_SHORT=2",
|
||||
"-DSIZEOF_SIZE_T=8",
|
||||
"-DSIZEOF_TIME_T=8",
|
||||
"-DSTDC_HEADERS=1",
|
||||
"-DSTRERROR_R_TYPE_ARG3=size_t",
|
||||
"-DTIME_WITH_SYS_TIME=1",
|
||||
"-DUSE_THREADS_POSIX=1",
|
||||
"-DUSE_UNIX_SOCKETS=1",
|
||||
|
||||
# Extra defines needed by curl
|
||||
"-DBUILDING_LIBCURL",
|
||||
"-DCURL_HIDDEN_SYMBOLS",
|
||||
]
|
||||
|
||||
LINUX_CURL_COPTS = [
|
||||
"-DHAVE_LINUX_TCP_H=1",
|
||||
"-DHAVE_MSG_NOSIGNAL=1",
|
||||
]
|
||||
|
||||
CURL_COPTS = select({
|
||||
"//:windows": [
|
||||
# Disable everything else except HTTP protocol.
|
||||
"/DHTTP_ONLY=1",
|
||||
"/DCURL_STATICLIB",
|
||||
"/DWIN32",
|
||||
"/DBUILDING_LIBCURL",
|
||||
"/DUSE_WIN32_IDN",
|
||||
"/DWANT_IDN_PROTOTYPES",
|
||||
"/DUSE_IPV6",
|
||||
"/DUSE_WINDOWS_SSPI",
|
||||
"/DUSE_SCHANNEL",
|
||||
],
|
||||
"//:osx": BASE_CURL_COPTS,
|
||||
"//conditions:default": BASE_CURL_COPTS + LINUX_CURL_COPTS,
|
||||
})
|
||||
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define {BASE_NAME}_EXPORT
|
||||
#define {BASE_NAME}_NO_EXPORT
|
||||
@@ -1,21 +0,0 @@
|
||||
def _generate_dummy_export_header_impl(ctx):
|
||||
ctx.actions.expand_template(
|
||||
template = ctx.file._template,
|
||||
output = ctx.outputs.header_file,
|
||||
substitutions = {
|
||||
"{BASE_NAME}": ctx.attr.basename,
|
||||
},
|
||||
)
|
||||
|
||||
generate_dummy_export_header = rule(
|
||||
attrs = {
|
||||
"basename": attr.string(mandatory = True),
|
||||
"header": attr.string(mandatory = True),
|
||||
"_template": attr.label(
|
||||
allow_single_file = True,
|
||||
default = Label("@com_github_jupp0r_prometheus_cpp//bazel:dummy_export.h.tpl"),
|
||||
),
|
||||
},
|
||||
implementation = _generate_dummy_export_header_impl,
|
||||
outputs = {"header_file": "%{header}"},
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
||||
|
||||
def prometheus_cpp_repositories():
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "civetweb",
|
||||
strip_prefix = "civetweb-1.15",
|
||||
sha256 = "90a533422944ab327a4fbb9969f0845d0dba05354f9cacce3a5005fa59f593b9",
|
||||
urls = [
|
||||
"https://github.com/civetweb/civetweb/archive/v1.15.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_google_googletest",
|
||||
sha256 = "b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5",
|
||||
strip_prefix = "googletest-release-1.11.0",
|
||||
urls = [
|
||||
"https://github.com/google/googletest/archive/release-1.11.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_github_curl",
|
||||
sha256 = "3c6893d38d054d4e378267166858698899e9d87258e8ff1419d020c395384535",
|
||||
strip_prefix = "curl-7.84.0",
|
||||
urls = [
|
||||
"https://github.com/curl/curl/releases/download/curl-7_84_0/curl-7.84.0.tar.gz",
|
||||
"https://curl.haxx.se/download/curl-7.84.0.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_github_google_benchmark",
|
||||
sha256 = "6132883bc8c9b0df5375b16ab520fac1a85dc9e4cf5be59480448ece74b278d4",
|
||||
strip_prefix = "benchmark-1.6.1",
|
||||
urls = [
|
||||
"https://github.com/google/benchmark/archive/v1.6.1.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "net_zlib_zlib",
|
||||
sha256 = "91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9",
|
||||
strip_prefix = "zlib-1.2.12",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/zlib.net/zlib-1.2.12.tar.gz",
|
||||
"https://zlib.net/zlib-1.2.12.tar.gz",
|
||||
"https://storage.googleapis.com/bazel-mirror/zlib.net/zlib-1.2.12.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:zlib.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "boringssl",
|
||||
# Use github mirror instead of https://boringssl.googlesource.com/boringssl
|
||||
# to obtain a boringssl archive with consistent sha256
|
||||
sha256 = "534fa658bd845fd974b50b10f444d392dfd0d93768c4a51b61263fd37d851c40",
|
||||
strip_prefix = "boringssl-b9232f9e27e5668bc0414879dcdedb2a59ea75f2",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
|
||||
"https://github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
|
||||
],
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
# copied from: https://github.com/bazelbuild/bazel/blob/master/third_party/zlib/BUILD
|
||||
|
||||
licenses(["notice"]) # BSD/MIT-like license (for zlib)
|
||||
|
||||
cc_library(
|
||||
name = "z",
|
||||
srcs = glob(["*.c"]),
|
||||
hdrs = glob(["*.h"]),
|
||||
# Use -Dverbose=-1 to turn off zlib's trace logging. (bazelbuild/bazel#3280)
|
||||
copts = [
|
||||
"-w",
|
||||
"-Dverbose=-1",
|
||||
],
|
||||
includes = ["."],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
[
|
||||
{ include: [ "@<gmock/.*>", private, "<gmock/gmock.h>", public ] },
|
||||
{ include: [ "@<gtest/.*>", private, "<gtest/gtest.h>", public ] },
|
||||
{ include: [ "@<bits/this_thread_sleep.h>", private, "<thread>", public ]}
|
||||
]
|
||||
@@ -1,15 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
project(prometheus-cpp-import)
|
||||
|
||||
find_package(prometheus-cpp CONFIG REQUIRED)
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PUSH)
|
||||
add_executable(sample-client sample_client.cc)
|
||||
target_link_libraries(sample-client PRIVATE prometheus-cpp::push)
|
||||
endif()
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PULL)
|
||||
add_executable(sample-server sample_server.cc)
|
||||
target_link_libraries(sample-server PRIVATE prometheus-cpp::pull)
|
||||
endif()
|
||||
@@ -1 +0,0 @@
|
||||
../../push/tests/integration/sample_client.cc
|
||||
@@ -1 +0,0 @@
|
||||
../../pull/tests/integration/sample_server.cc
|
||||
@@ -1,21 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
project(prometheus-cpp-import)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(PROMETHEUS_CPP_CORE REQUIRED prometheus-cpp-core)
|
||||
pkg_check_modules(PROMETHEUS_CPP_PUSH IMPORTED_TARGET prometheus-cpp-push)
|
||||
pkg_check_modules(PROMETHEUS_CPP_PULL IMPORTED_TARGET prometheus-cpp-pull)
|
||||
|
||||
if(PROMETHEUS_CPP_PUSH_FOUND)
|
||||
add_executable(sample-client sample_client.cc)
|
||||
target_link_libraries(sample-client PRIVATE PkgConfig::PROMETHEUS_CPP_PUSH)
|
||||
endif()
|
||||
|
||||
if(PROMETHEUS_CPP_PULL_FOUND)
|
||||
add_executable(sample-server sample_server.cc)
|
||||
target_link_libraries(sample-server PRIVATE PkgConfig::PROMETHEUS_CPP_PULL)
|
||||
endif()
|
||||
@@ -1 +0,0 @@
|
||||
../../push/tests/integration/sample_client.cc
|
||||
@@ -1 +0,0 @@
|
||||
../../pull/tests/integration/sample_server.cc
|
||||
@@ -1,34 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
set_and_check(prometheus-cpp_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
||||
|
||||
set(PROMETHEUS_CPP_ENABLE_PULL @ENABLE_PULL@)
|
||||
set(PROMETHEUS_CPP_ENABLE_PUSH @ENABLE_PUSH@)
|
||||
set(PROMETHEUS_CPP_USE_COMPRESSION @ENABLE_COMPRESSION@)
|
||||
set(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES @USE_THIRDPARTY_LIBRARIES@)
|
||||
set(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL @THIRDPARTY_CIVETWEB_WITH_SSL@)
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_dependency(Threads)
|
||||
unset(CMAKE_THREAD_PREFER_PTHREAD)
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PULL)
|
||||
if(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES)
|
||||
if(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL)
|
||||
find_dependency(OpenSSL)
|
||||
endif()
|
||||
else()
|
||||
find_dependency(civetweb)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PULL AND PROMETHEUS_CPP_USE_COMPRESSION)
|
||||
find_dependency(ZLIB)
|
||||
endif()
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PUSH)
|
||||
find_dependency(CURL)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/prometheus-cpp-targets.cmake")
|
||||
@@ -1,14 +0,0 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@-core
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
URL: @PROJECT_HOMEPAGE_URL@
|
||||
Version: @PROJECT_VERSION@
|
||||
Requires:
|
||||
Requires.private: @PKGCONFIG_REQUIRES@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -l@PROJECT_NAME@-core
|
||||
Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@
|
||||
@@ -1,14 +0,0 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@-pull
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
URL: @PROJECT_HOMEPAGE_URL@
|
||||
Version: @PROJECT_VERSION@
|
||||
Requires: @PROJECT_NAME@-core
|
||||
Requires.private: @PKGCONFIG_REQUIRES@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -l@PROJECT_NAME@-pull
|
||||
Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@
|
||||
@@ -1,14 +0,0 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@-push
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
URL: @PROJECT_HOMEPAGE_URL@
|
||||
Version: @PROJECT_VERSION@
|
||||
Requires: @PROJECT_NAME@-core
|
||||
Requires.private: @PKGCONFIG_REQUIRES@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -l@PROJECT_NAME@-push
|
||||
Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@
|
||||
@@ -1,20 +0,0 @@
|
||||
load("//bazel:export_header.bzl", "generate_dummy_export_header")
|
||||
|
||||
generate_dummy_export_header(
|
||||
name = "export_header",
|
||||
basename = "PROMETHEUS_CPP_CORE",
|
||||
header = "include/prometheus/detail/core_export.h",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "core",
|
||||
srcs = glob([
|
||||
"src/**/*.cc",
|
||||
"src/**/*.h",
|
||||
]),
|
||||
hdrs = glob(
|
||||
["include/**/*.h"],
|
||||
) + [":export_header"],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
add_library(core
|
||||
src/check_names.cc
|
||||
src/counter.cc
|
||||
src/detail/builder.cc
|
||||
src/detail/ckms_quantiles.cc
|
||||
src/detail/time_window_quantiles.cc
|
||||
src/detail/utils.cc
|
||||
src/family.cc
|
||||
src/gauge.cc
|
||||
src/histogram.cc
|
||||
src/info.cc
|
||||
src/registry.cc
|
||||
src/serializer.cc
|
||||
src/summary.cc
|
||||
src/text_serializer.cc
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME}::core ALIAS core)
|
||||
|
||||
target_compile_features(core
|
||||
PUBLIC
|
||||
cxx_std_14
|
||||
)
|
||||
|
||||
target_link_libraries(core
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
$<$<AND:$<BOOL:UNIX>,$<NOT:$<BOOL:APPLE>>>:rt>
|
||||
)
|
||||
|
||||
if(HAVE_CXX_LIBATOMIC)
|
||||
# the exported library config must use libatomic unconditionally
|
||||
# (the HAVE_CXX_LIBATOMIC variable should not leak into the target config)
|
||||
target_link_libraries(core PUBLIC atomic)
|
||||
endif()
|
||||
|
||||
target_include_directories(core
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
)
|
||||
|
||||
set_target_properties(core
|
||||
PROPERTIES
|
||||
OUTPUT_NAME ${PROJECT_NAME}-core
|
||||
DEFINE_SYMBOL PROMETHEUS_CPP_CORE_EXPORTS
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
)
|
||||
|
||||
generate_export_header(core
|
||||
BASE_NAME ${PROJECT_NAME}-core
|
||||
EXPORT_FILE_NAME include/prometheus/detail/core_export.h
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS core
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
if(GENERATE_PKGCONFIG)
|
||||
set(PKGCONFIG_LIBS)
|
||||
set(PKGCONFIG_REQUIRES)
|
||||
|
||||
if(HAVE_CXX_LIBATOMIC)
|
||||
string(APPEND PKGCONFIG_LIBS " -latomic")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/cmake/prometheus-cpp-core.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc
|
||||
@ONLY
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
unset(PKGCONFIG_LIBS)
|
||||
unset(PKGCONFIG_REQUIRES)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(benchmark_FOUND)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
@@ -1,12 +0,0 @@
|
||||
cc_binary(
|
||||
name = "benchmarks",
|
||||
srcs = glob([
|
||||
"*.cc",
|
||||
"*.h",
|
||||
]),
|
||||
linkstatic = True,
|
||||
deps = [
|
||||
"//core",
|
||||
"@com_github_google_benchmark//:benchmark",
|
||||
],
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
add_executable(benchmarks
|
||||
main.cc
|
||||
benchmark_helpers.cc
|
||||
benchmark_helpers.h
|
||||
counter_bench.cc
|
||||
gauge_bench.cc
|
||||
histogram_bench.cc
|
||||
info_bench.cc
|
||||
registry_bench.cc
|
||||
summary_bench.cc
|
||||
)
|
||||
|
||||
target_link_libraries(benchmarks
|
||||
PRIVATE
|
||||
${PROJECT_NAME}::core
|
||||
benchmark::benchmark
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME benchmarks
|
||||
COMMAND benchmarks
|
||||
)
|
||||
|
||||
set_property(
|
||||
TEST benchmarks
|
||||
APPEND PROPERTY LABELS Benchmark
|
||||
)
|
||||
@@ -1,26 +0,0 @@
|
||||
#include "benchmark_helpers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
std::string GenerateRandomString(std::size_t length) {
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
|
||||
const std::size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[rand() % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
prometheus::Labels GenerateRandomLabels(std::size_t number_of_pairs) {
|
||||
const auto label_character_count = 10;
|
||||
auto label_pairs = prometheus::Labels{};
|
||||
for (std::size_t i = 0; i < number_of_pairs; i++) {
|
||||
label_pairs.insert({GenerateRandomString(label_character_count),
|
||||
GenerateRandomString(label_character_count)});
|
||||
}
|
||||
return label_pairs;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
std::string GenerateRandomString(std::size_t length);
|
||||
prometheus::Labels GenerateRandomLabels(std::size_t number_of_labels);
|
||||
@@ -1,33 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/counter.h"
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Counter_Increment(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family =
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
auto& counter = counter_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) counter.Increment();
|
||||
}
|
||||
BENCHMARK(BM_Counter_Increment);
|
||||
|
||||
static void BM_Counter_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family =
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
auto& counter = counter_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(counter.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Counter_Collect);
|
||||
@@ -1,59 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/gauge.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Gauge_Increment(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.Increment(2);
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Increment);
|
||||
|
||||
static void BM_Gauge_Decrement(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.Decrement(2);
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Decrement);
|
||||
|
||||
static void BM_Gauge_SetToCurrentTime(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.SetToCurrentTime();
|
||||
}
|
||||
BENCHMARK(BM_Gauge_SetToCurrentTime);
|
||||
|
||||
static void BM_Gauge_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(gauge.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Collect);
|
||||
@@ -1,70 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/histogram.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
using prometheus::Histogram;
|
||||
|
||||
static Histogram::BucketBoundaries CreateLinearBuckets(std::int64_t start,
|
||||
std::int64_t end,
|
||||
std::int64_t step) {
|
||||
auto bucket_boundaries = Histogram::BucketBoundaries{};
|
||||
for (auto i = start; i < end; i += step) {
|
||||
bucket_boundaries.push_back(i);
|
||||
}
|
||||
return bucket_boundaries;
|
||||
}
|
||||
|
||||
static void BM_Histogram_Observe(benchmark::State& state) {
|
||||
using prometheus::BuildHistogram;
|
||||
using prometheus::Histogram;
|
||||
using prometheus::Registry;
|
||||
|
||||
const auto number_of_buckets = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& histogram_family =
|
||||
BuildHistogram().Name("benchmark_histogram").Help("").Register(registry);
|
||||
auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1);
|
||||
auto& histogram = histogram_family.Add({}, bucket_boundaries);
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, number_of_buckets);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
histogram.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Histogram_Observe)->Range(0, 4096);
|
||||
|
||||
static void BM_Histogram_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildHistogram;
|
||||
using prometheus::Histogram;
|
||||
using prometheus::Registry;
|
||||
|
||||
const auto number_of_buckets = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& histogram_family =
|
||||
BuildHistogram().Name("benchmark_histogram").Help("").Register(registry);
|
||||
auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1);
|
||||
auto& histogram = histogram_family.Add({}, bucket_boundaries);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(histogram.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Histogram_Collect)->Range(0, 4096);
|
||||
@@ -1,20 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/info.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Info_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildInfo;
|
||||
using prometheus::Info;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& info_family =
|
||||
BuildInfo().Name("benchmark_info").Help("").Register(registry);
|
||||
auto& info = info_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(info.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Info_Collect);
|
||||
@@ -1,3 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
@@ -1,44 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "benchmark_helpers.h"
|
||||
#include "prometheus/counter.h"
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Registry_CreateFamily(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
|
||||
while (state.KeepRunning())
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
}
|
||||
BENCHMARK(BM_Registry_CreateFamily);
|
||||
|
||||
static void BM_Registry_CreateCounter(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family = BuildCounter()
|
||||
.Labels(GenerateRandomLabels(10))
|
||||
.Name("benchmark_counter")
|
||||
.Help("")
|
||||
.Register(registry);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto labels = GenerateRandomLabels(state.range(0));
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
counter_family.Add(labels);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Registry_CreateCounter)->Range(0, 4096);
|
||||
@@ -1,139 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/registry.h"
|
||||
#include "prometheus/summary.h"
|
||||
|
||||
using prometheus::Summary;
|
||||
|
||||
static const auto ITERATIONS = 262144;
|
||||
|
||||
static Summary::Quantiles CreateLinearQuantiles(int count) {
|
||||
static auto generator = [](double x) {
|
||||
static auto exp = [](double x) {
|
||||
static const double A = 2;
|
||||
return 1 - std::exp(-A * x);
|
||||
};
|
||||
|
||||
return exp(x) / exp(1);
|
||||
};
|
||||
|
||||
auto quantiles = Summary::Quantiles{};
|
||||
for (auto i = 0; i < count; ++i) {
|
||||
quantiles.emplace_back(generator(double(i) / count), 0.01);
|
||||
}
|
||||
return quantiles;
|
||||
}
|
||||
|
||||
static void BM_Summary_Observe(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_quantiles = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto quantiles = CreateLinearQuantiles(number_of_quantiles);
|
||||
auto& summary = summary_family.Add({}, quantiles);
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
summary.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Observe)->Range(0, 64)->Iterations(ITERATIONS);
|
||||
|
||||
static void BM_Summary_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_quantiles = state.range(0);
|
||||
const auto number_of_entries = state.range(1);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto quantiles = CreateLinearQuantiles(number_of_quantiles);
|
||||
auto& summary = summary_family.Add({}, quantiles);
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen));
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(summary.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Collect)->RangePair(0, 64, 0, ITERATIONS);
|
||||
|
||||
static void BM_Summary_Observe_Common(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto& summary = summary_family.Add(
|
||||
{}, Summary::Quantiles{
|
||||
{0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}});
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
summary.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Observe_Common)->Iterations(ITERATIONS);
|
||||
|
||||
static void BM_Summary_Collect_Common(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_entries = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto& summary = summary_family.Add(
|
||||
{}, Summary::Quantiles{
|
||||
{0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}});
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen));
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(summary.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Collect_Common)->Range(0, ITERATIONS);
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
PROMETHEUS_CPP_CORE_EXPORT bool CheckMetricName(const std::string& name);
|
||||
PROMETHEUS_CPP_CORE_EXPORT bool CheckLabelName(const std::string& name,
|
||||
MetricType type);
|
||||
} // namespace prometheus
|
||||
@@ -1,90 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT ClientMetric {
|
||||
// Label
|
||||
|
||||
struct Label {
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
bool operator<(const Label& rhs) const {
|
||||
return std::tie(name, value) < std::tie(rhs.name, rhs.value);
|
||||
}
|
||||
|
||||
bool operator==(const Label& rhs) const {
|
||||
return std::tie(name, value) == std::tie(rhs.name, rhs.value);
|
||||
}
|
||||
};
|
||||
std::vector<Label> label;
|
||||
|
||||
// Counter
|
||||
|
||||
struct Counter {
|
||||
double value = 0.0;
|
||||
};
|
||||
Counter counter;
|
||||
|
||||
// Gauge
|
||||
|
||||
struct Gauge {
|
||||
double value = 0.0;
|
||||
};
|
||||
Gauge gauge;
|
||||
|
||||
// Info
|
||||
|
||||
struct Info {
|
||||
double value = 1.0;
|
||||
};
|
||||
Info info;
|
||||
|
||||
// Summary
|
||||
|
||||
struct Quantile {
|
||||
double quantile = 0.0;
|
||||
double value = 0.0;
|
||||
};
|
||||
|
||||
struct Summary {
|
||||
std::uint64_t sample_count = 0;
|
||||
double sample_sum = 0.0;
|
||||
std::vector<Quantile> quantile;
|
||||
};
|
||||
Summary summary;
|
||||
|
||||
// Histogram
|
||||
|
||||
struct Bucket {
|
||||
std::uint64_t cumulative_count = 0;
|
||||
double upper_bound = 0.0;
|
||||
};
|
||||
|
||||
struct Histogram {
|
||||
std::uint64_t sample_count = 0;
|
||||
double sample_sum = 0.0;
|
||||
std::vector<Bucket> bucket;
|
||||
};
|
||||
Histogram histogram;
|
||||
|
||||
// Untyped
|
||||
|
||||
struct Untyped {
|
||||
double value = 0;
|
||||
};
|
||||
Untyped untyped;
|
||||
|
||||
// Timestamp
|
||||
|
||||
std::int64_t timestamp_ms = 0;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
namespace prometheus {
|
||||
struct MetricFamily;
|
||||
}
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// @brief Interface implemented by anything that can be used by Prometheus to
|
||||
/// collect metrics.
|
||||
///
|
||||
/// A Collectable has to be registered for collection. See Registry.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Collectable {
|
||||
public:
|
||||
virtual ~Collectable() = default;
|
||||
|
||||
/// \brief Returns a list of metrics and their samples.
|
||||
virtual std::vector<MetricFamily> Collect() const = 0;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -1,82 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/detail/builder.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/gauge.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A counter metric to represent a monotonically increasing value.
|
||||
///
|
||||
/// This class represents the metric type counter:
|
||||
/// https://prometheus.io/docs/concepts/metric_types/#counter
|
||||
///
|
||||
/// The value of the counter can only increase. Example of counters are:
|
||||
/// - the number of requests served
|
||||
/// - tasks completed
|
||||
/// - errors
|
||||
///
|
||||
/// Do not use a counter to expose a value that can decrease - instead use a
|
||||
/// Gauge.
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Counter {
|
||||
public:
|
||||
static const MetricType metric_type{MetricType::Counter};
|
||||
|
||||
/// \brief Create a counter that starts at 0.
|
||||
Counter() = default;
|
||||
|
||||
/// \brief Increment the counter by 1.
|
||||
void Increment();
|
||||
|
||||
/// \brief Increment the counter by a given amount.
|
||||
///
|
||||
/// The counter will not change if the given amount is negative.
|
||||
void Increment(double);
|
||||
|
||||
/// \brief Get the current value of the counter.
|
||||
double Value() const;
|
||||
|
||||
/// \brief Get the current value of the counter.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
|
||||
private:
|
||||
Gauge gauge_{0.0};
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Counter metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& counter_family = prometheus::BuildCounter()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - Labels(const Labels&) to assign a set of
|
||||
/// key-value pairs (= labels) to the metric.
|
||||
///
|
||||
/// To finish the configuration of the Counter metric, register it with
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Counter> BuildCounter();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
// IWYU pragma: private
|
||||
// IWYU pragma: no_include "prometheus/family.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
template <typename T>
|
||||
class Family; // IWYU pragma: keep
|
||||
class Registry; // IWYU pragma: keep
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class Builder {
|
||||
public:
|
||||
Builder& Labels(const ::prometheus::Labels& labels);
|
||||
Builder& Name(const std::string&);
|
||||
Builder& Help(const std::string&);
|
||||
Family<T>& Register(Registry&);
|
||||
|
||||
private:
|
||||
::prometheus::Labels labels_;
|
||||
std::string name_;
|
||||
std::string help_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
// IWYU pragma: private, include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT CKMSQuantiles {
|
||||
public:
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT Quantile {
|
||||
Quantile(double quantile, double error);
|
||||
|
||||
double quantile;
|
||||
double error;
|
||||
double u;
|
||||
double v;
|
||||
};
|
||||
|
||||
private:
|
||||
struct Item {
|
||||
double value;
|
||||
int g;
|
||||
int delta;
|
||||
|
||||
Item(double value, int lower_delta, int delta);
|
||||
};
|
||||
|
||||
public:
|
||||
explicit CKMSQuantiles(const std::vector<Quantile>& quantiles);
|
||||
|
||||
void insert(double value);
|
||||
double get(double q);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
double allowableError(int rank);
|
||||
bool insertBatch();
|
||||
void compress();
|
||||
|
||||
private:
|
||||
const std::reference_wrapper<const std::vector<Quantile>> quantiles_;
|
||||
|
||||
std::size_t count_;
|
||||
std::vector<Item> sample_;
|
||||
std::array<double, 500> buffer_;
|
||||
std::size_t buffer_count_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/ckms_quantiles.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
// IWYU pragma: private, include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT TimeWindowQuantiles {
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
public:
|
||||
TimeWindowQuantiles(const std::vector<CKMSQuantiles::Quantile>& quantiles,
|
||||
Clock::duration max_age_seconds, int age_buckets);
|
||||
|
||||
double get(double q) const;
|
||||
void insert(double value);
|
||||
|
||||
private:
|
||||
CKMSQuantiles& rotate() const;
|
||||
|
||||
const std::vector<CKMSQuantiles::Quantile>& quantiles_;
|
||||
mutable std::vector<CKMSQuantiles> ckms_quantiles_;
|
||||
mutable std::size_t current_bucket_;
|
||||
|
||||
mutable Clock::time_point last_rotation_;
|
||||
const Clock::duration rotation_interval_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
/// \brief Label hasher for use in STL containers.
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT LabelHasher {
|
||||
/// \brief Compute the hash value of a map of labels.
|
||||
///
|
||||
/// \param labels The map that will be computed the hash value.
|
||||
///
|
||||
/// \returns The hash value of the given labels.
|
||||
std::size_t operator()(const Labels& labels) const;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -1,156 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/collectable.h"
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/detail/utils.h"
|
||||
#include "prometheus/labels.h"
|
||||
#include "prometheus/metric_family.h"
|
||||
|
||||
// IWYU pragma: no_include "prometheus/counter.h"
|
||||
// IWYU pragma: no_include "prometheus/gauge.h"
|
||||
// IWYU pragma: no_include "prometheus/histogram.h"
|
||||
// IWYU pragma: no_include "prometheus/info.h"
|
||||
// IWYU pragma: no_include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A metric of type T with a set of labeled dimensions.
|
||||
///
|
||||
/// One of Prometheus main feature is a multi-dimensional data model with time
|
||||
/// series data identified by metric name and key/value pairs, also known as
|
||||
/// labels. A time series is a series of data points indexed (or listed or
|
||||
/// graphed) in time order (https://en.wikipedia.org/wiki/Time_series).
|
||||
///
|
||||
/// An instance of this class is exposed as multiple time series during
|
||||
/// scrape, i.e., one time series for each set of labels provided to Add().
|
||||
///
|
||||
/// For example it is possible to collect data for a metric
|
||||
/// `http_requests_total`, with two time series:
|
||||
///
|
||||
/// - all HTTP requests that used the method POST
|
||||
/// - all HTTP requests that used the method GET
|
||||
///
|
||||
/// The metric name specifies the general feature of a system that is
|
||||
/// measured, e.g., `http_requests_total`. Labels enable Prometheus's
|
||||
/// dimensional data model: any given combination of labels for the same
|
||||
/// metric name identifies a particular dimensional instantiation of that
|
||||
/// metric. For example a label for 'all HTTP requests that used the method
|
||||
/// POST' can be assigned with `method= "POST"`.
|
||||
///
|
||||
/// Given a metric name and a set of labels, time series are frequently
|
||||
/// identified using this notation:
|
||||
///
|
||||
/// <metric name> { < label name >= <label value>, ... }
|
||||
///
|
||||
/// It is required to follow the syntax of metric names and labels given by:
|
||||
/// https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
|
||||
///
|
||||
/// The following metric and label conventions are not required for using
|
||||
/// Prometheus, but can serve as both a style-guide and a collection of best
|
||||
/// practices: https://prometheus.io/docs/practices/naming/
|
||||
///
|
||||
/// \tparam T One of the metric types Counter, Gauge, Histogram or Summary.
|
||||
template <typename T>
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {
|
||||
public:
|
||||
/// \brief Create a new metric.
|
||||
///
|
||||
/// Every metric is uniquely identified by its name and a set of key-value
|
||||
/// pairs, also known as labels. Prometheus's query language allows filtering
|
||||
/// and aggregation based on metric name and these labels.
|
||||
///
|
||||
/// This example selects all time series that have the `http_requests_total`
|
||||
/// metric name:
|
||||
///
|
||||
/// http_requests_total
|
||||
///
|
||||
/// It is possible to assign labels to the metric name. These labels are
|
||||
/// propagated to each dimensional data added with Add(). For example if a
|
||||
/// label `job= "prometheus"` is provided to this constructor, it is possible
|
||||
/// to filter this time series with Prometheus's query language by appending
|
||||
/// a set of labels to match in curly braces ({})
|
||||
///
|
||||
/// http_requests_total{job= "prometheus"}
|
||||
///
|
||||
/// For further information see: [Querying Basics]
|
||||
/// (https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||||
///
|
||||
/// \param name Set the metric name.
|
||||
/// \param help Set an additional description.
|
||||
/// \param constant_labels Assign a set of key-value pairs (= labels) to the
|
||||
/// metric. All these labels are propagated to each time series within the
|
||||
/// metric.
|
||||
/// \throw std::runtime_exception on invalid metric or label names.
|
||||
Family(const std::string& name, const std::string& help,
|
||||
const Labels& constant_labels);
|
||||
|
||||
/// \brief Add a new dimensional data.
|
||||
///
|
||||
/// Each new set of labels adds a new dimensional data and is exposed in
|
||||
/// Prometheus as a time series. It is possible to filter the time series
|
||||
/// with Prometheus's query language by appending a set of labels to match in
|
||||
/// curly braces ({})
|
||||
///
|
||||
/// http_requests_total{job= "prometheus",method= "POST"}
|
||||
///
|
||||
/// \param labels Assign a set of key-value pairs (= labels) to the
|
||||
/// dimensional data. The function does nothing, if the same set of labels
|
||||
/// already exists.
|
||||
/// \param args Arguments are passed to the constructor of metric type T. See
|
||||
/// Counter, Gauge, Histogram or Summary for required constructor arguments.
|
||||
/// \return Return the newly created dimensional data or - if a same set of
|
||||
/// labels already exists - the already existing dimensional data.
|
||||
/// \throw std::runtime_exception on invalid label names.
|
||||
template <typename... Args>
|
||||
T& Add(const Labels& labels, Args&&... args) {
|
||||
return Add(labels, std::make_unique<T>(args...));
|
||||
}
|
||||
|
||||
/// \brief Remove the given dimensional data.
|
||||
///
|
||||
/// \param metric Dimensional data to be removed. The function does nothing,
|
||||
/// if the given metric was not returned by Add().
|
||||
void Remove(T* metric);
|
||||
|
||||
/// \brief Returns true if the dimensional data with the given labels exist
|
||||
///
|
||||
/// \param labels A set of key-value pairs (= labels) of the dimensional data.
|
||||
bool Has(const Labels& labels) const;
|
||||
|
||||
/// \brief Returns the name for this family.
|
||||
///
|
||||
/// \return The family name.
|
||||
const std::string& GetName() const;
|
||||
|
||||
/// \brief Returns the constant labels for this family.
|
||||
///
|
||||
/// \return All constant labels as key-value pairs.
|
||||
const Labels& GetConstantLabels() const;
|
||||
|
||||
/// \brief Returns the current value of each dimensional data.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
///
|
||||
/// \return Zero or more samples for each dimensional data.
|
||||
std::vector<MetricFamily> Collect() const override;
|
||||
|
||||
private:
|
||||
std::unordered_map<Labels, std::unique_ptr<T>, detail::LabelHasher> metrics_;
|
||||
|
||||
const std::string name_;
|
||||
const std::string help_;
|
||||
const Labels constant_labels_;
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
ClientMetric CollectMetric(const Labels& labels, T* metric) const;
|
||||
T& Add(const Labels& labels, std::unique_ptr<T> object);
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user