diff --git a/.cicd/defaults.json b/.cicd/defaults.json index 3ec177b341..09326de0b9 100644 --- a/.cicd/defaults.json +++ b/.cicd/defaults.json @@ -3,7 +3,7 @@ "target":"4", "prerelease":false }, - "eossystemcontracts":{ - "ref":"release/3.2" + "referencecontracts":{ + "ref":"main" } } diff --git a/.cicd/platforms/asan.Dockerfile b/.cicd/platforms/asan.Dockerfile new file mode 100644 index 0000000000..23ac698b14 --- /dev/null +++ b/.cicd/platforms/asan.Dockerfile @@ -0,0 +1,37 @@ +# syntax=docker/dockerfile:1 +FROM ubuntu:jammy +ENV TZ="America/New_York" +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y build-essential \ + cmake \ + git \ + jq \ + libcurl4-openssl-dev \ + libgmp-dev \ + llvm-11-dev \ + lsb-release \ + ninja-build \ + python3-numpy \ + software-properties-common \ + file \ + wget \ + zlib1g-dev \ + zstd + +RUN yes | bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" llvm.sh 18 + +#make sure no confusion on what llvm library leap's cmake should pick up on +RUN rm -rf /usr/lib/llvm-18/lib/cmake + +ENV LEAP_PLATFORM_HAS_EXTRAS_CMAKE=1 +COPY <<-EOF /extras.cmake + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) + + set(CMAKE_C_COMPILER "clang-18" CACHE STRING "") + set(CMAKE_CXX_COMPILER "clang++-18" CACHE STRING "") + set(CMAKE_C_FLAGS "-fsanitize=address -fno-omit-frame-pointer" CACHE STRING "") + set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer" CACHE STRING "") +EOF + +ENV ASAN_OPTIONS=detect_leaks=0 diff --git a/.cicd/platforms/asserton.Dockerfile b/.cicd/platforms/asserton.Dockerfile new file mode 100644 index 0000000000..a80cfc417f --- /dev/null +++ b/.cicd/platforms/asserton.Dockerfile @@ -0,0 +1,29 @@ +# syntax=docker/dockerfile:1 +#the exact version of Ubuntu doesn't matter for the purpose of asserton builds. Feel free to upgrade in future +FROM ubuntu:jammy +ENV TZ="America/New_York" +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y build-essential \ + cmake \ + git \ + jq \ + libcurl4-openssl-dev \ + libgmp-dev \ + llvm-11-dev \ + ninja-build \ + python3-numpy \ + file \ + zlib1g-dev \ + zstd + +ENV LEAP_PLATFORM_HAS_EXTRAS_CMAKE=1 +COPY <<-EOF /extras.cmake + # reset the build type to empty to disable any cmake default flags + set(CMAKE_BUILD_TYPE "" CACHE STRING "" FORCE) + + set(CMAKE_C_FLAGS "-O3" CACHE STRING "") + set(CMAKE_CXX_FLAGS "-O3" CACHE STRING "") + + set(LEAP_ENABLE_RELEASE_BUILD_TEST "Off" CACHE BOOL "") +EOF diff --git a/.cicd/platforms/ubsan.Dockerfile b/.cicd/platforms/ubsan.Dockerfile new file mode 100644 index 0000000000..bf7720b5e6 --- /dev/null +++ b/.cicd/platforms/ubsan.Dockerfile @@ -0,0 +1,42 @@ +# syntax=docker/dockerfile:1 +FROM ubuntu:jammy +ENV TZ="America/New_York" +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y build-essential \ + cmake \ + git \ + jq \ + libcurl4-openssl-dev \ + libgmp-dev \ + llvm-11-dev \ + lsb-release \ + ninja-build \ + python3-numpy \ + software-properties-common \ + file \ + wget \ + zlib1g-dev \ + zstd + +RUN yes | bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" llvm.sh 18 + +#make sure no confusion on what llvm library leap's cmake should pick up on +RUN rm -rf /usr/lib/llvm-18/lib/cmake + +COPY <<-EOF /ubsan.supp + vptr:wasm_eosio_validation.hpp + vptr:wasm_eosio_injection.hpp +EOF + +ENV LEAP_PLATFORM_HAS_EXTRAS_CMAKE=1 +COPY <<-EOF /extras.cmake + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) + + set(CMAKE_C_COMPILER "clang-18" CACHE STRING "") + set(CMAKE_CXX_COMPILER "clang++-18" CACHE STRING "") + set(CMAKE_C_FLAGS "-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING "") + set(CMAKE_CXX_FLAGS "-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING "") +EOF + +ENV UBSAN_OPTIONS=print_stacktrace=1,suppressions=/ubsan.supp diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8c42f6dc30..7f42f51044 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -18,8 +18,8 @@ on: - default - true - false - override-eos-system-contracts: - description: 'Override eos-system-contracts ref' + override-reference-contracts: + description: 'Override reference contracts ref' type: string permissions: @@ -57,9 +57,9 @@ jobs: outputs: cdt-target: ${{steps.versions.outputs.cdt-target}} cdt-prerelease: ${{steps.versions.outputs.cdt-prerelease}} - eos-system-contracts-ref: ${{steps.versions.outputs.eos-system-contracts-ref}} + reference-contracts-ref: ${{steps.versions.outputs.reference-contracts-ref}} steps: - - name: Setup cdt and eos-system-contracts versions + - name: Setup cdt and reference-contracts versions id: versions env: GH_TOKEN: ${{secrets.GITHUB_TOKEN}} @@ -67,7 +67,7 @@ jobs: DEFAULTS_JSON=$(curl -sSfL $(gh api https://api.github.com/repos/${{github.repository}}/contents/.cicd/defaults.json?ref=${{github.sha}} --jq .download_url)) echo cdt-target=$(echo "$DEFAULTS_JSON" | jq -r '.cdt.target') >> $GITHUB_OUTPUT echo cdt-prerelease=$(echo "$DEFAULTS_JSON" | jq -r '.cdt.prerelease') >> $GITHUB_OUTPUT - echo eos-system-contracts-ref=$(echo "$DEFAULTS_JSON" | jq -r '.eossystemcontracts.ref') >> $GITHUB_OUTPUT + echo reference-contracts-ref=$(echo "$DEFAULTS_JSON" | jq -r '.referencecontracts.ref') >> $GITHUB_OUTPUT if [[ "${{inputs.override-cdt}}" != "" ]]; then echo cdt-target=${{inputs.override-cdt}} >> $GITHUB_OUTPUT @@ -75,8 +75,8 @@ jobs: if [[ "${{inputs.override-cdt-prerelease}}" == +(true|false) ]]; then echo cdt-prerelease=${{inputs.override-cdt-prerelease}} >> $GITHUB_OUTPUT fi - if [[ "${{inputs.override-eos-system-contracts}}" != "" ]]; then - echo eos-system-contracts-ref=${{inputs.override-eos-system-contracts}} >> $GITHUB_OUTPUT + if [[ "${{inputs.override-reference-contracts}}" != "" ]]; then + echo reference-contracts-ref=${{inputs.override-reference-contracts}} >> $GITHUB_OUTPUT fi package: @@ -93,7 +93,7 @@ jobs: with: submodules: recursive - name: Download builddir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{matrix.platform}}-build - name: Build packages @@ -112,17 +112,19 @@ jobs: run: | python3 -c "from TestHarness import Cluster" - name: Upload dev package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.platform != 'reproducible' with: name: leap-dev-${{matrix.platform}}-amd64 path: build/leap-dev*.deb + compression-level: 0 - name: Upload leap package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.platform == 'reproducible' with: name: leap-deb-amd64 path: build/leap_*.deb + compression-level: 0 tests: name: Tests (${{matrix.cfg.name}}) @@ -133,6 +135,9 @@ jobs: include: - cfg: {name: 'ubuntu20', base: 'ubuntu20', builddir: 'ubuntu20'} - cfg: {name: 'ubuntu22', base: 'ubuntu22', builddir: 'ubuntu22'} + - cfg: {name: 'asserton', base: 'asserton', builddir: 'asserton'} + - cfg: {name: 'ubsan', base: 'ubsan', builddir: 'ubsan'} + - cfg: {name: 'asan', base: 'asan', builddir: 'asan'} - cfg: {name: 'ubuntu20repro', base: 'ubuntu20', builddir: 'reproducible'} - cfg: {name: 'ubuntu22repro', base: 'ubuntu22', builddir: 'reproducible'} runs-on: ["self-hosted", "enf-x86-hightier"] @@ -142,7 +147,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Download builddir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{matrix.cfg.builddir}}-build - name: Run Parallel Tests @@ -153,12 +158,13 @@ jobs: cd build ctest --output-on-failure -j $(nproc) -LE "(nonparallelizable_tests|long_running_tests)" --timeout 420 - name: Upload core files from failed tests - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{matrix.cfg.name}}-tests-logs if-no-files-found: ignore path: /cores + compression-level: 0 - name: Check CPU Features run: awk 'BEGIN {err = 1} /bmi2/ && /adx/ {err = 0} END {exit err}' /proc/cpuinfo @@ -171,13 +177,15 @@ jobs: include: - cfg: {name: 'ubuntu20', base: 'ubuntu20', builddir: 'ubuntu20'} - cfg: {name: 'ubuntu22', base: 'ubuntu22', builddir: 'ubuntu22'} + - cfg: {name: 'asserton', base: 'asserton', builddir: 'asserton'} + - cfg: {name: 'ubsan', base: 'ubsan', builddir: 'ubsan'} - cfg: {name: 'ubuntu20repro', base: 'ubuntu20', builddir: 'reproducible'} - cfg: {name: 'ubuntu22repro', base: 'ubuntu22', builddir: 'reproducible'} runs-on: ["self-hosted", "enf-x86-midtier"] steps: - uses: actions/checkout@v4 - name: Download builddir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{matrix.cfg.builddir}}-build - name: Run tests in parallel containers @@ -192,13 +200,14 @@ jobs: run: docker run --mount type=bind,source=/var/lib/systemd/coredump,target=/cores alpine sh -c 'tar -C /cores/ -c .' | tar x if: failure() - name: Upload logs from failed tests - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{matrix.cfg.name}}-np-logs path: | *-logs.tar.gz core*.zst + compression-level: 0 lr-tests: name: LR Tests (${{matrix.cfg.name}}) @@ -209,13 +218,15 @@ jobs: include: - cfg: {name: 'ubuntu20', base: 'ubuntu20', builddir: 'ubuntu20'} - cfg: {name: 'ubuntu22', base: 'ubuntu22', builddir: 'ubuntu22'} + - cfg: {name: 'asserton', base: 'asserton', builddir: 'asserton'} + - cfg: {name: 'ubsan', base: 'ubsan', builddir: 'ubsan'} - cfg: {name: 'ubuntu20repro', base: 'ubuntu20', builddir: 'reproducible'} - cfg: {name: 'ubuntu22repro', base: 'ubuntu22', builddir: 'reproducible'} runs-on: ["self-hosted", "enf-x86-lowtier"] steps: - uses: actions/checkout@v4 - name: Download builddir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{matrix.cfg.builddir}}-build - name: Run tests in parallel containers @@ -230,13 +241,14 @@ jobs: run: docker run --mount type=bind,source=/var/lib/systemd/coredump,target=/cores alpine sh -c 'tar -C /cores/ -c .' | tar x if: failure() - name: Upload logs from failed tests - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{matrix.cfg.name}}-lr-logs path: | *-logs.tar.gz core*.zst + compression-level: 0 libtester-tests: name: libtester tests @@ -244,10 +256,10 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu20, ubuntu22] + platform: [ubuntu22] test: [build-tree, make-dev-install, deb-install] runs-on: ["self-hosted", "enf-x86-midtier"] - container: ${{ matrix.test != 'deb-install' && fromJSON(needs.platform-cache.outputs.platforms)[matrix.platform].image || matrix.platform == 'ubuntu20' && 'ubuntu:focal' || 'ubuntu:jammy' }} + container: ${{ matrix.test != 'deb-install' && fromJSON(needs.platform-cache.outputs.platforms)[matrix.platform].image || 'ubuntu:jammy' }} env: DEBIAN_FRONTEND: noninteractive TZ: Etc/UTC @@ -265,7 +277,7 @@ jobs: submodules: recursive - if: ${{ matrix.test != 'deb-install' }} name: Download leap builddir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{matrix.platform}}-build - if: ${{ matrix.test != 'deb-install' }} @@ -287,7 +299,7 @@ jobs: rm -r * - if: ${{ matrix.test == 'deb-install' }} name: Download leap-dev - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: leap-dev-${{matrix.platform}}-amd64 - if: ${{ matrix.test == 'deb-install' }} @@ -312,21 +324,21 @@ jobs: rm ./*.deb # Reference Contracts - - name: checkout eos-system-contracts + - name: checkout reference-contracts uses: actions/checkout@v4 with: - repository: eosnetworkfoundation/eos-system-contracts - path: eos-system-contracts - ref: '${{needs.v.outputs.eos-system-contracts-ref}}' + repository: AntelopeIO/reference-contracts + path: reference-contracts + ref: '${{needs.v.outputs.reference-contracts-ref}}' - if: ${{ matrix.test == 'deb-install' }} - name: Install eos-system-contracts deps + name: Install reference-contracts deps run: | apt-get -y install cmake build-essential - - name: Build & Test eos-system-contracts + - name: Build & Test reference-contracts run: | - cmake -S eos-system-contracts -B eos-system-contracts/build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=On -DSYSTEM_ENABLE_LEAP_VERSION_CHECK=Off -DSYSTEM_ENABLE_CDT_VERSION_CHECK=Off - cmake --build eos-system-contracts/build -- -j $(nproc) - cd eos-system-contracts/build/tests + cmake -S reference-contracts -B reference-contracts/build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=On -DSYSTEM_ENABLE_LEAP_VERSION_CHECK=Off -DSYSTEM_ENABLE_CDT_VERSION_CHECK=Off + cmake --build reference-contracts/build -- -j $(nproc) + cd reference-contracts/build/tests ctest --output-on-failure -j $(nproc) all-passing: diff --git a/.github/workflows/build_base.yaml b/.github/workflows/build_base.yaml index ec0b70f95b..ce885e22ad 100644 --- a/.github/workflows/build_base.yaml +++ b/.github/workflows/build_base.yaml @@ -38,11 +38,12 @@ jobs: run: | # https://github.com/actions/runner/issues/2033 chown -R $(id -u):$(id -g) $PWD - cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LEAP_DEV_DEB=On -GNinja + cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LEAP_DEV_DEB=On ${LEAP_PLATFORM_HAS_EXTRAS_CMAKE:+-C /extras.cmake} -GNinja cmake --build build tar -pc --exclude "*.o" build | zstd --long -T0 -9 > build.tar.zst - name: Upload builddir - uses: AntelopeIO/upload-artifact-large-chunks-action@v1 + uses: actions/upload-artifact@v4 with: name: ${{matrix.platform}}-build - path: build.tar.zst \ No newline at end of file + path: build.tar.zst + compression-level: 0 \ No newline at end of file diff --git a/.github/workflows/pinned_build.yaml b/.github/workflows/pinned_build.yaml new file mode 100644 index 0000000000..1d2e735b0b --- /dev/null +++ b/.github/workflows/pinned_build.yaml @@ -0,0 +1,11 @@ +name: "Pinned Build" + +on: + workflow_dispatch: + +jobs: + dummy: + runs-on: ubuntu-latest + steps: + - name: Dummy + run: echo This workflow is a stub on main to allow it to be manually run on 3.x/4.0 diff --git a/.github/workflows/submod.yaml b/.github/workflows/submod.yaml index 5de18efc94..35d9281185 100644 --- a/.github/workflows/submod.yaml +++ b/.github/workflows/submod.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout run: | - git clone https://github.com/${GITHUB_REPOSITORY} . + git clone https://x-access-token:${{github.token}}@github.com/${GITHUB_REPOSITORY} . git fetch -v --prune origin +refs/pull/${PR_NUMBER}/merge:refs/remotes/pull/${PR_NUMBER}/merge git checkout --force --progress refs/remotes/pull/${PR_NUMBER}/merge git submodule sync --recursive diff --git a/CMakeLists.txt b/CMakeLists.txt index ed5b4736dd..8ae187bcdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,9 @@ set( CMAKE_CXX_EXTENSIONS ON ) set( CXX_STANDARD_REQUIRED ON) set(VERSION_MAJOR 5) -set(VERSION_MINOR 0) -set(VERSION_PATCH 2) -#set(VERSION_SUFFIX rc3) +set(VERSION_MINOR 1) +set(VERSION_PATCH 0) +set(VERSION_SUFFIX dev) if(VERSION_SUFFIX) set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}") diff --git a/CMakeModules/CMakeASM-LLVMWARInformation.cmake b/CMakeModules/CMakeASM-LLVMWARInformation.cmake old mode 100755 new mode 100644 diff --git a/CMakeModules/CMakeDetermineASM-LLVMWARCompiler.cmake b/CMakeModules/CMakeDetermineASM-LLVMWARCompiler.cmake old mode 100755 new mode 100644 diff --git a/CMakeModules/CMakeTestASM-LLVMWARCompiler.cmake b/CMakeModules/CMakeTestASM-LLVMWARCompiler.cmake old mode 100755 new mode 100644 diff --git a/README.md b/README.md index c5fc400c57..bb71157b19 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ # Leap + +1. [Branches](#branches) +2. [Supported Operating Systems](#supported-operating-systems) +3. [Binary Installation](#binary-installation) +4. [Build and Install from Source](#build-and-install-from-source) +5. [Bash Autocomplete](#bash-autocomplete) + 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. ## Branches @@ -208,3 +215,10 @@ It is also possible to install using `make` instead: ```bash sudo make install ``` + +## Bash Autocomplete +`cleos` and `leap-util` offer a substantial amount of functionality. Consider using bash's autocompletion support which makes it easier to discover all their various options. + +For our provided `.deb` packages simply install Ubuntu's `bash-completion` package: `apt-get install bash-completion` (you may need to log out/in after installing). + +If building from source install the `build/programs/cleos/bash-completion/completions/cleos` and `build/programs/leap-util/bash-completion/completions/leap-util` files to your bash-completion directory. Refer to [bash-completion's documentation](https://github.com/scop/bash-completion#faq) on the possible install locations. diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index 3d36b24f04..a53a3bc466 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -111,8 +111,6 @@ Config Options for eosio::producer_plugin: --disable-subjective-api-billing arg (=1) Disable subjective CPU billing for API transactions - --producer-threads arg (=2) Number of worker threads in producer - thread pool --snapshots-dir arg (="snapshots") the location of the snapshots directory (absolute path or relative to application data dir) diff --git a/docs/02_cleos/03_command-reference/convert/index.md b/docs/02_cleos/03_command-reference/convert/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/convert/pack_action_data.md b/docs/02_cleos/03_command-reference/convert/pack_action_data.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/convert/pack_transaction.md b/docs/02_cleos/03_command-reference/convert/pack_transaction.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/convert/unpack_action_data.md b/docs/02_cleos/03_command-reference/convert/unpack_action_data.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/convert/unpack_transaction.md b/docs/02_cleos/03_command-reference/convert/unpack_transaction.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/create/account.md b/docs/02_cleos/03_command-reference/create/account.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/create/index.md b/docs/02_cleos/03_command-reference/create/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/create/key.md b/docs/02_cleos/03_command-reference/create/key.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/accounts.md b/docs/02_cleos/03_command-reference/get/accounts.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/block.md b/docs/02_cleos/03_command-reference/get/block.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/code.md b/docs/02_cleos/03_command-reference/get/code.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/currency-balance.md b/docs/02_cleos/03_command-reference/get/currency-balance.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/currency-stats.md b/docs/02_cleos/03_command-reference/get/currency-stats.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/currency.md b/docs/02_cleos/03_command-reference/get/currency.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/index.md b/docs/02_cleos/03_command-reference/get/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/info.md b/docs/02_cleos/03_command-reference/get/info.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/schedule.md b/docs/02_cleos/03_command-reference/get/schedule.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/servants.md b/docs/02_cleos/03_command-reference/get/servants.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/table.md b/docs/02_cleos/03_command-reference/get/table.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/transaction.md b/docs/02_cleos/03_command-reference/get/transaction.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/get/transaction_id.md b/docs/02_cleos/03_command-reference/get/transaction_id.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/index.md b/docs/02_cleos/03_command-reference/multisig/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-approve.md b/docs/02_cleos/03_command-reference/multisig/multisig-approve.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-cancel.md b/docs/02_cleos/03_command-reference/multisig/multisig-cancel.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-exec.md b/docs/02_cleos/03_command-reference/multisig/multisig-exec.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-invalidate.md b/docs/02_cleos/03_command-reference/multisig/multisig-invalidate.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-propose.md b/docs/02_cleos/03_command-reference/multisig/multisig-propose.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-propose_trx.md b/docs/02_cleos/03_command-reference/multisig/multisig-propose_trx.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-review.md b/docs/02_cleos/03_command-reference/multisig/multisig-review.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/multisig/multisig-unapprove.md b/docs/02_cleos/03_command-reference/multisig/multisig-unapprove.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/net/index.md b/docs/02_cleos/03_command-reference/net/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/push/index.md b/docs/02_cleos/03_command-reference/push/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/push/push-action.md b/docs/02_cleos/03_command-reference/push/push-action.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/push/push-transaction.md b/docs/02_cleos/03_command-reference/push/push-transaction.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/push/push-transactions.md b/docs/02_cleos/03_command-reference/push/push-transactions.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/set/index.md b/docs/02_cleos/03_command-reference/set/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/set/set-abi.md b/docs/02_cleos/03_command-reference/set/set-abi.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/set/set-code.md b/docs/02_cleos/03_command-reference/set/set-code.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/set/set-contract.md b/docs/02_cleos/03_command-reference/set/set-contract.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/index.md b/docs/02_cleos/03_command-reference/system/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-bidname.md b/docs/02_cleos/03_command-reference/system/system-bidname.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-bidnameinfo.md b/docs/02_cleos/03_command-reference/system/system-bidnameinfo.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-buyram.md b/docs/02_cleos/03_command-reference/system/system-buyram.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-canceldelay.md b/docs/02_cleos/03_command-reference/system/system-canceldelay.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-claimrewards.md b/docs/02_cleos/03_command-reference/system/system-claimrewards.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-delegatebw.md b/docs/02_cleos/03_command-reference/system/system-delegatebw.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-listbw.md b/docs/02_cleos/03_command-reference/system/system-listbw.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-listproducers.md b/docs/02_cleos/03_command-reference/system/system-listproducers.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-newaccount.md b/docs/02_cleos/03_command-reference/system/system-newaccount.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-regproducer.md b/docs/02_cleos/03_command-reference/system/system-regproducer.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-regproxy.md b/docs/02_cleos/03_command-reference/system/system-regproxy.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-buyrex.md b/docs/02_cleos/03_command-reference/system/system-rex-buyrex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-cancelrexorder.md b/docs/02_cleos/03_command-reference/system/system-rex-cancelrexorder.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-closerex.md b/docs/02_cleos/03_command-reference/system/system-rex-closerex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-consolidate.md b/docs/02_cleos/03_command-reference/system/system-rex-consolidate.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-defundcpuloan.md b/docs/02_cleos/03_command-reference/system/system-rex-defundcpuloan.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-defundnetloan.md b/docs/02_cleos/03_command-reference/system/system-rex-defundnetloan.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-deposit.md b/docs/02_cleos/03_command-reference/system/system-rex-deposit.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-fundcpuloan.md b/docs/02_cleos/03_command-reference/system/system-rex-fundcpuloan.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-fundnetloan.md b/docs/02_cleos/03_command-reference/system/system-rex-fundnetloan.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-lendrex.md b/docs/02_cleos/03_command-reference/system/system-rex-lendrex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-mvfromsavings.md b/docs/02_cleos/03_command-reference/system/system-rex-mvfromsavings.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-mvtosavings.md b/docs/02_cleos/03_command-reference/system/system-rex-mvtosavings.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-rentcpu.md b/docs/02_cleos/03_command-reference/system/system-rex-rentcpu.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-rentnet.md b/docs/02_cleos/03_command-reference/system/system-rex-rentnet.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-rexexec.md b/docs/02_cleos/03_command-reference/system/system-rex-rexexec.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-sellrex.md b/docs/02_cleos/03_command-reference/system/system-rex-sellrex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-unstaketorex.md b/docs/02_cleos/03_command-reference/system/system-rex-unstaketorex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-updaterex.md b/docs/02_cleos/03_command-reference/system/system-rex-updaterex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex-withdraw.md b/docs/02_cleos/03_command-reference/system/system-rex-withdraw.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-rex.md b/docs/02_cleos/03_command-reference/system/system-rex.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-sellram.md b/docs/02_cleos/03_command-reference/system/system-sellram.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-undelegatebw.md b/docs/02_cleos/03_command-reference/system/system-undelegatebw.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-unregprod.md b/docs/02_cleos/03_command-reference/system/system-unregprod.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-unregproxy.md b/docs/02_cleos/03_command-reference/system/system-unregproxy.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer-approve.md b/docs/02_cleos/03_command-reference/system/system-voteproducer-approve.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer-prods.md b/docs/02_cleos/03_command-reference/system/system-voteproducer-prods.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer-proxy.md b/docs/02_cleos/03_command-reference/system/system-voteproducer-proxy.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer-unapprove.md b/docs/02_cleos/03_command-reference/system/system-voteproducer-unapprove.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer.md b/docs/02_cleos/03_command-reference/system/system-voteproducer.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/transfer.md b/docs/02_cleos/03_command-reference/transfer.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/version/client.md b/docs/02_cleos/03_command-reference/version/client.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/version/index.md b/docs/02_cleos/03_command-reference/version/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/create.md b/docs/02_cleos/03_command-reference/wallet/create.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/create_key.md b/docs/02_cleos/03_command-reference/wallet/create_key.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/import.md b/docs/02_cleos/03_command-reference/wallet/import.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/index.md b/docs/02_cleos/03_command-reference/wallet/index.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/keys.md b/docs/02_cleos/03_command-reference/wallet/keys.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/list.md b/docs/02_cleos/03_command-reference/wallet/list.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/lock.md b/docs/02_cleos/03_command-reference/wallet/lock.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/lock_all.md b/docs/02_cleos/03_command-reference/wallet/lock_all.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/open.md b/docs/02_cleos/03_command-reference/wallet/open.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/private_keys.md b/docs/02_cleos/03_command-reference/wallet/private_keys.md old mode 100755 new mode 100644 diff --git a/docs/02_cleos/03_command-reference/wallet/unlock.md b/docs/02_cleos/03_command-reference/wallet/unlock.md old mode 100755 new mode 100644 diff --git a/libraries/appbase b/libraries/appbase index b75b31e14f..d7a7580dd7 160000 --- a/libraries/appbase +++ b/libraries/appbase @@ -1 +1 @@ -Subproject commit b75b31e14f966fa3de6246e120dcba36c6ce5264 +Subproject commit d7a7580dd7ff1d8e7979157abc869865a3a43220 diff --git a/libraries/builtins/README.txt b/libraries/builtins/README.txt old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixdfti.c b/libraries/builtins/fixdfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixsfti.c b/libraries/builtins/fixsfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixtfti.c b/libraries/builtins/fixtfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixunsdfti.c b/libraries/builtins/fixunsdfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixunssfti.c b/libraries/builtins/fixunssfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/fixunstfti.c b/libraries/builtins/fixunstfti.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/floattidf.c b/libraries/builtins/floattidf.c old mode 100755 new mode 100644 diff --git a/libraries/builtins/floatuntidf.c b/libraries/builtins/floatuntidf.c old mode 100755 new mode 100644 diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 67f51fc8bf..ba37c30284 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -88,8 +88,8 @@ add_library( eosio_chain transaction.cpp block.cpp block_header.cpp - block_header_state.cpp - block_state.cpp + block_header_state_legacy.cpp + block_state_legacy.cpp fork_database.cpp controller.cpp authorization_manager.cpp diff --git a/libraries/chain/abi_serializer.cpp b/libraries/chain/abi_serializer.cpp index 1cb039fd4a..7cfeecbe75 100644 --- a/libraries/chain/abi_serializer.cpp +++ b/libraries/chain/abi_serializer.cpp @@ -415,7 +415,7 @@ namespace eosio { namespace chain { fc::raw::unpack(stream, size); } EOS_RETHROW_EXCEPTIONS( unpack_exception, "Unable to unpack size of array '${p}'", ("p", ctx.get_path_string()) ) vector vars; - vars.reserve(size); + vars.reserve(std::min(size.value, 1024u)); // limit the maximum size that can be reserved before data is read auto h1 = ctx.push_to_path( impl::array_index_path_item{} ); for( decltype(size.value) i = 0; i < size; ++i ) { ctx.set_array_index_of_path_back(i); diff --git a/libraries/chain/authorization_manager.cpp b/libraries/chain/authorization_manager.cpp index 9cb4580a0c..7b60554161 100644 --- a/libraries/chain/authorization_manager.cpp +++ b/libraries/chain/authorization_manager.cpp @@ -479,7 +479,12 @@ namespace eosio { namespace chain { auto effective_provided_delay = (provided_delay >= delay_max_limit) ? fc::microseconds::maximum() : provided_delay; - auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; }, + auto checker = make_auth_checker( [&](const permission_level& p) -> const shared_authority* { + if(const permission_object* po = find_permission(p)) + return &po->auth; + else + return nullptr; + }, _control.get_global_properties().configuration.max_authority_depth, provided_keys, provided_permissions, @@ -580,7 +585,12 @@ namespace eosio { namespace chain { auto delay_max_limit = fc::seconds( _control.get_global_properties().configuration.max_transaction_delay ); - auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; }, + auto checker = make_auth_checker( [&](const permission_level& p) -> const shared_authority* { + if(const permission_object* po = find_permission(p)) + return &po->auth; + else + return nullptr; + }, _control.get_global_properties().configuration.max_authority_depth, provided_keys, provided_permissions, @@ -611,7 +621,12 @@ namespace eosio { namespace chain { fc::microseconds provided_delay )const { - auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; }, + auto checker = make_auth_checker( [&](const permission_level& p) -> const shared_authority* { + if(const permission_object* po = find_permission(p)) + return &po->auth; + else + return nullptr; + }, _control.get_global_properties().configuration.max_authority_depth, candidate_keys, {}, diff --git a/libraries/chain/block_header_state.cpp b/libraries/chain/block_header_state_legacy.cpp similarity index 94% rename from libraries/chain/block_header_state.cpp rename to libraries/chain/block_header_state_legacy.cpp index b7cd3036ac..81ad77373b 100644 --- a/libraries/chain/block_header_state.cpp +++ b/libraries/chain/block_header_state_legacy.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -15,13 +15,13 @@ namespace eosio { namespace chain { } } - producer_authority block_header_state::get_scheduled_producer( block_timestamp_type t )const { + producer_authority block_header_state_legacy::get_scheduled_producer( block_timestamp_type t )const { auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions); index /= config::producer_repetitions; return active_schedule.producers[index]; } - uint32_t block_header_state::calc_dpos_last_irreversible( account_name producer_of_next_block )const { + uint32_t block_header_state_legacy::calc_dpos_last_irreversible( account_name producer_of_next_block )const { vector blocknums; blocknums.reserve( producer_to_last_implied_irb.size() ); for( auto& i : producer_to_last_implied_irb ) { blocknums.push_back( (i.first == producer_of_next_block) ? dpos_proposed_irreversible_blocknum : i.second); @@ -35,10 +35,10 @@ namespace eosio { namespace chain { return blocknums[ index ]; } - pending_block_header_state block_header_state::next( block_timestamp_type when, - uint16_t num_prev_blocks_to_confirm )const + pending_block_header_state_legacy block_header_state_legacy::next( block_timestamp_type when, + uint16_t num_prev_blocks_to_confirm )const { - pending_block_header_state result; + pending_block_header_state_legacy result; if( when != block_timestamp_type() ) { EOS_ASSERT( when > header.timestamp, block_validate_exception, "next block must be in the future" ); @@ -170,7 +170,7 @@ namespace eosio { namespace chain { return result; } - signed_block_header pending_block_header_state::make_block_header( + signed_block_header pending_block_header_state_legacy::make_block_header( const checksum256_type& transaction_mroot, const checksum256_type& action_mroot, const std::optional& new_producers, @@ -221,7 +221,7 @@ namespace eosio { namespace chain { return h; } - block_header_state pending_block_header_state::_finish_next( + block_header_state_legacy pending_block_header_state_legacy::_finish_next( const signed_block_header& h, const protocol_feature_set& pfs, const std::function(this) ) ); + block_header_state_legacy result( std::move( *static_cast(this) ) ); result.id = h.calculate_id(); result.header = h; @@ -317,7 +317,7 @@ namespace eosio { namespace chain { return result; } - block_header_state pending_block_header_state::finish_next( + block_header_state_legacy pending_block_header_state_legacy::finish_next( const signed_block_header& h, vector&& additional_signatures, const protocol_feature_set& pfs, @@ -347,7 +347,7 @@ namespace eosio { namespace chain { return result; } - block_header_state pending_block_header_state::finish_next( + block_header_state_legacy pending_block_header_state_legacy::finish_next( signed_block_header& h, const protocol_feature_set& pfs, const std::function&& _additional_signatures, const protocol_feature_set& pfs, @@ -390,12 +390,12 @@ namespace eosio { namespace chain { return next( h.timestamp, h.confirmed ).finish_next( h, std::move(_additional_signatures), pfs, validator, skip_validate_signee ); } - digest_type block_header_state::sig_digest()const { + digest_type block_header_state_legacy::sig_digest()const { auto header_bmroot = digest_type::hash( std::make_pair( header.digest(), blockroot_merkle.get_root() ) ); return digest_type::hash( std::make_pair(header_bmroot, pending_schedule.schedule_hash) ); } - void block_header_state::sign( const signer_callback_type& signer ) { + void block_header_state_legacy::sign( const signer_callback_type& signer ) { auto d = sig_digest(); auto sigs = signer( d ); @@ -408,7 +408,7 @@ namespace eosio { namespace chain { verify_signee(); } - void block_header_state::verify_signee( )const { + void block_header_state_legacy::verify_signee( )const { auto num_keys_in_authority = std::visit([](const auto &a){ return a.keys.size(); }, valid_block_signing_authority); EOS_ASSERT(1 + additional_signatures.size() <= num_keys_in_authority, wrong_signing_key, @@ -444,7 +444,7 @@ namespace eosio { namespace chain { /** * Reference cannot outlive *this. Assumes header_exts is not mutated after instatiation. */ - const vector& block_header_state::get_new_protocol_feature_activations()const { + const vector& block_header_state_legacy::get_new_protocol_feature_activations()const { static const vector no_activations{}; if( header_exts.count(protocol_feature_activation::extension_id()) == 0 ) @@ -453,7 +453,7 @@ namespace eosio { namespace chain { return std::get(header_exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features; } - block_header_state::block_header_state( legacy::snapshot_block_header_state_v2&& snapshot ) + block_header_state_legacy::block_header_state_legacy( legacy::snapshot_block_header_state_v2&& snapshot ) { block_num = snapshot.block_num; dpos_proposed_irreversible_blocknum = snapshot.dpos_proposed_irreversible_blocknum; diff --git a/libraries/chain/block_state.cpp b/libraries/chain/block_state_legacy.cpp similarity index 67% rename from libraries/chain/block_state.cpp rename to libraries/chain/block_state_legacy.cpp index fd614a6118..532e89d16c 100644 --- a/libraries/chain/block_state.cpp +++ b/libraries/chain/block_state_legacy.cpp @@ -1,4 +1,4 @@ -#include +#include #include namespace eosio { namespace chain { @@ -47,13 +47,13 @@ namespace eosio { namespace chain { */ template - block_header_state inject_additional_signatures( pending_block_header_state&& cur, - signed_block& b, - const protocol_feature_set& pfs, - Extras&& ... extras ) + block_header_state_legacy inject_additional_signatures( pending_block_header_state_legacy&& cur, + signed_block& b, + const protocol_feature_set& pfs, + Extras&& ... extras ) { auto pfa = cur.prev_activated_protocol_features; - block_header_state result = std::move(cur).finish_next(b, pfs, std::forward(extras)...); + block_header_state_legacy result = std::move(cur).finish_next(b, pfs, std::forward(extras)...); if (!result.additional_signatures.empty()) { bool wtmsig_enabled = detail::is_builtin_activated(pfa, pfs, builtin_protocol_feature_t::wtmsig_block_signatures); @@ -74,28 +74,28 @@ namespace eosio { namespace chain { } - block_state::block_state( const block_header_state& prev, - signed_block_ptr b, - const protocol_feature_set& pfs, - const std::function&, const vector& )>& validator, bool skip_validate_signee ) - :block_header_state( prev.next( *b, extract_additional_signatures(b, pfs, prev.activated_protocol_features), pfs, validator, skip_validate_signee ) ) + :block_header_state_legacy( prev.next( *b, extract_additional_signatures(b, pfs, prev.activated_protocol_features), pfs, validator, skip_validate_signee ) ) ,block( std::move(b) ) {} - block_state::block_state( pending_block_header_state&& cur, - signed_block_ptr&& b, - deque&& trx_metas, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - const signer_callback_type& signer + block_state_legacy::block_state_legacy( pending_block_header_state_legacy&& cur, + signed_block_ptr&& b, + deque&& trx_metas, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + const signer_callback_type& signer ) - :block_header_state( inject_additional_signatures( std::move(cur), *b, pfs, validator, signer ) ) + :block_header_state_legacy( inject_additional_signatures( std::move(cur), *b, pfs, validator, signer ) ) ,block( std::move(b) ) ,_pub_keys_recovered( true ) // called by produce_block so signature recovery of trxs must have been done ,_cached_trxs( std::move(trx_metas) ) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index d61c23737e..b79210526f 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -113,16 +113,16 @@ class maybe_session { }; struct building_block { - building_block( const block_header_state& prev, + building_block( const block_header_state_legacy& prev, block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector& new_protocol_feature_activations ) - :_pending_block_header_state( prev.next( when, num_prev_blocks_to_confirm ) ) + :_pending_block_header_state_legacy( prev.next( when, num_prev_blocks_to_confirm ) ) ,_new_protocol_feature_activations( new_protocol_feature_activations ) ,_trx_mroot_or_receipt_digests( digests_t{} ) {} - pending_block_header_state _pending_block_header_state; + pending_block_header_state_legacy _pending_block_header_state_legacy; std::optional _new_pending_producer_schedule; vector _new_protocol_feature_activations; size_t _num_new_protocol_features_that_have_activated = 0; @@ -134,7 +134,7 @@ struct building_block { struct assembled_block { block_id_type _id; - pending_block_header_state _pending_block_header_state; + pending_block_header_state_legacy _pending_block_header_state_legacy; deque _trx_metas; signed_block_ptr _unsigned_block; @@ -143,13 +143,13 @@ struct assembled_block { }; struct completed_block { - block_state_ptr _block_state; + block_state_legacy_ptr _block_state; }; using block_stage_type = std::variant; struct pending_state { - pending_state( maybe_session&& s, const block_header_state& prev, + pending_state( maybe_session&& s, const block_header_state_legacy& prev, block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector& new_protocol_feature_activations ) @@ -164,11 +164,11 @@ struct pending_state { controller::block_report _block_report{}; /** @pre _block_stage cannot hold completed_block alternative */ - const pending_block_header_state& get_pending_block_header_state()const { + const pending_block_header_state_legacy& get_pending_block_header_state_legacy()const { if( std::holds_alternative(_block_stage) ) - return std::get(_block_stage)._pending_block_header_state; + return std::get(_block_stage)._pending_block_header_state_legacy; - return std::get(_block_stage)._pending_block_header_state; + return std::get(_block_stage)._pending_block_header_state_legacy; } deque extract_trx_metas() { @@ -184,7 +184,7 @@ struct pending_state { bool is_protocol_feature_activated( const digest_type& feature_digest )const { if( std::holds_alternative(_block_stage) ) { auto& bb = std::get(_block_stage); - const auto& activated_features = bb._pending_block_header_state.prev_activated_protocol_features->protocol_features; + const auto& activated_features = bb._pending_block_header_state_legacy.prev_activated_protocol_features->protocol_features; if( activated_features.find( feature_digest ) != activated_features.end() ) return true; @@ -220,19 +220,24 @@ struct controller_impl { // Read-write tasks are not being executed. }; - // LLVM sets the new handler, we need to reset this to throw a bad_alloc exception so we can possibly exit cleanly - // and not just abort. +#if LLVM_VERSION_MAJOR < 9 + // LLVM versions prior to 9 do a set_new_handler() in a static global initializer. Reset LLVM's custom handler + // back to the default behavior of throwing bad_alloc so we can possibly exit cleanly and not just abort as LLVM's + // handler does. + // LLVM 9+ doesn't install this handler unless calling InitLLVM(), which we don't. + // See https://reviews.llvm.org/D64505 struct reset_new_handler { reset_new_handler() { std::set_new_handler([](){ throw std::bad_alloc(); }); } }; reset_new_handler rnh; // placed here to allow for this to be set before constructing the other fields +#endif controller& self; std::function shutdown; chainbase::database db; block_log blog; std::optional pending; - block_state_ptr head; + block_state_legacy_ptr head; fork_database fork_db; resource_limits_manager resource_limits; subjective_billing subjective_bill; @@ -343,8 +348,9 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); - self.irreversible_block.connect([this](const block_state_ptr& bsp) { - wasmif.current_lib(bsp->block_num); + self.irreversible_block.connect([this](const block_signal_params& t) { + const auto& [ block, id] = t; + wasmif.current_lib(block->block_num()); }); @@ -369,7 +375,7 @@ struct controller_impl { } /** - * Plugins / observers listening to signals emited (such as accepted_transaction) might trigger + * Plugins / observers listening to signals emited might trigger * errors and throw exceptions. Unless those exceptions are caught it could impact consensus and/or * cause a node to fork. * @@ -449,7 +455,7 @@ struct controller_impl { apply_block( br, *bitr, controller::block_status::complete, trx_meta_cache_lookup{} ); } - emit( self.irreversible_block, *bitr ); + emit( self.irreversible_block, std::tie((*bitr)->block, (*bitr)->id) ); // blog.append could fail due to failures like running out of space. // Do it before commit so that in case it throws, DB can be rolled back. @@ -485,7 +491,7 @@ struct controller_impl { producer_authority_schedule initial_schedule = { 0, { producer_authority{config::system_account_name, block_signing_authority_v0{ 1, {{genesis.initial_key, 1}} } } } }; legacy::producer_schedule_type initial_legacy_schedule{ 0, {{config::system_account_name, genesis.initial_key}} }; - block_header_state genheader; + block_header_state_legacy genheader; genheader.active_schedule = initial_schedule; genheader.pending_schedule.schedule = initial_schedule; // NOTE: if wtmsig block signatures are enabled at genesis time this should be the hash of a producer authority schedule @@ -495,8 +501,8 @@ struct controller_impl { genheader.id = genheader.header.calculate_id(); genheader.block_num = genheader.header.block_num(); - head = std::make_shared(); - static_cast(*head) = genheader; + head = std::make_shared(); + static_cast(*head) = genheader; head->activated_protocol_features = std::make_shared(); head->block = std::make_shared(genheader.header); db.set_revision( head->block_num ); @@ -852,8 +858,8 @@ struct controller_impl { section.add_row(chain_snapshot_header(), db); }); - snapshot->write_section([this]( auto §ion ){ - section.template add_row(*head, db); + snapshot->write_section("eosio::chain::block_state", [this]( auto §ion ){ + section.template add_row(*head, db); }); controller_index_set::walk_indices([this, &snapshot]( auto utils ){ @@ -903,17 +909,17 @@ struct controller_impl { }); { /// load and upgrade the block header state - block_header_state head_header_state; + block_header_state_legacy head_header_state; using v2 = legacy::snapshot_block_header_state_v2; if (std::clamp(header.version, v2::minimum_version, v2::maximum_version) == header.version ) { - snapshot->read_section([this, &head_header_state]( auto §ion ) { + snapshot->read_section("eosio::chain::block_state", [this, &head_header_state]( auto §ion ) { legacy::snapshot_block_header_state_v2 legacy_header_state; section.read_row(legacy_header_state, db); - head_header_state = block_header_state(std::move(legacy_header_state)); + head_header_state = block_header_state_legacy(std::move(legacy_header_state)); }); } else { - snapshot->read_section([this,&head_header_state]( auto §ion ){ + snapshot->read_section("eosio::chain::block_state", [this,&head_header_state]( auto §ion ){ section.read_row(head_header_state, db); }); } @@ -927,8 +933,8 @@ struct controller_impl { ("block_log_last_num", blog_end) ); - head = std::make_shared(); - static_cast(*head) = head_header_state; + head = std::make_shared(); + static_cast(*head) = head_header_state; } controller_index_set::walk_indices([this, &snapshot, &header]( auto utils ){ @@ -1337,7 +1343,6 @@ struct controller_impl { 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()) ); undo_session.squash(); @@ -1403,7 +1408,6 @@ struct controller_impl { trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); - emit( self.accepted_transaction, trx ); dmlog_applied_transaction(trace); emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) ); @@ -1448,7 +1452,6 @@ struct controller_impl { 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(); @@ -1494,13 +1497,11 @@ struct controller_impl { trace->receipt = push_receipt(gtrx.trx_id, transaction_receipt::hard_fail, cpu_time_to_bill_us, 0); trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); - emit( self.accepted_transaction, trx ); dmlog_applied_transaction(trace); emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) ); undo_session.squash(); } else { - emit( self.accepted_transaction, trx ); dmlog_applied_transaction(trace); emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) ); } @@ -1634,7 +1635,6 @@ struct controller_impl { // call the accept signal but only once for this transaction if (!trx->accepted) { trx->accepted = true; - emit(self.accepted_transaction, trx); } dmlog_applied_transaction(trace, &trn); @@ -1681,7 +1681,6 @@ struct controller_impl { } if (!trx->is_transient()) { - emit(self.accepted_transaction, trx); dmlog_applied_transaction(trace); emit(self.applied_transaction, std::tie(trace, trx->packed_trx())); @@ -1730,7 +1729,7 @@ struct controller_impl { pending->_producer_block_id = producer_block_id; auto& bb = std::get(pending->_block_stage); - const auto& pbhs = bb._pending_block_header_state; + const auto& pbhs = bb._pending_block_header_state_legacy; // 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) @@ -1794,11 +1793,8 @@ struct controller_impl { db.modify( pso, [&]( auto& ps ) { ps.preactivated_protocol_features.clear(); - ps.activated_protocol_features.reserve( ps.activated_protocol_features.size() - + new_protocol_feature_activations.size() ); - for( const auto& feature_digest : new_protocol_feature_activations ) { - ps.activated_protocol_features.emplace_back( feature_digest, pbhs.block_num ); - } + for (const auto& digest : new_protocol_feature_activations) + ps.activated_protocol_features.emplace_back(digest, pbhs.block_num); }); } @@ -1871,7 +1867,7 @@ struct controller_impl { try { - auto& pbhs = pending->get_pending_block_header_state(); + auto& pbhs = pending->get_pending_block_header_state_legacy(); auto& bb = std::get(pending->_block_stage); @@ -1930,7 +1926,7 @@ struct controller_impl { pending->_block_stage = assembled_block{ id, - std::move( bb._pending_block_header_state ), + std::move( bb._pending_block_header_state_legacy ), std::move( bb._pending_trx_metas ), std::move( block_ptr ), std::move( bb._new_pending_producer_schedule ) @@ -1954,7 +1950,7 @@ struct controller_impl { if( s == controller::block_status::incomplete ) { fork_db.add( bsp ); fork_db.mark_valid( bsp ); - emit( self.accepted_block_header, bsp ); + emit( self.accepted_block_header, std::tie(bsp->block, bsp->id) ); EOS_ASSERT( bsp == fork_db.head(), fork_database_exception, "committed block did not become the new head in fork database"); } else if (s != controller::block_status::irreversible) { fork_db.mark_valid( bsp ); @@ -1966,7 +1962,7 @@ struct controller_impl { dm_logger->on_accepted_block(bsp); } - emit( self.accepted_block, bsp ); + emit( self.accepted_block, std::tie(bsp->block, bsp->id) ); if( s == controller::block_status::incomplete ) { log_irreversible(); @@ -2064,7 +2060,7 @@ struct controller_impl { } - void apply_block( controller::block_report& br, const block_state_ptr& bsp, controller::block_status s, + void apply_block( controller::block_report& br, const block_state_legacy_ptr& bsp, controller::block_status s, const trx_meta_cache_lookup& trx_lookup ) { try { try { @@ -2188,13 +2184,13 @@ struct controller_impl { // thread safe, expected to be called from thread other than the main thread - block_state_ptr create_block_state_i( const block_id_type& id, const signed_block_ptr& b, const block_header_state& prev ) { + block_state_legacy_ptr create_block_state_i( const block_id_type& id, const signed_block_ptr& b, const block_header_state_legacy& prev ) { auto trx_mroot = calculate_trx_merkle( b->transactions ); EOS_ASSERT( b->transaction_mroot == trx_mroot, block_validate_exception, "invalid block transaction merkle root ${b} != ${c}", ("b", b->transaction_mroot)("c", trx_mroot) ); const bool skip_validate_signee = false; - auto bsp = std::make_shared( + auto bsp = std::make_shared( prev, b, protocol_features.get_protocol_feature_set(), @@ -2210,7 +2206,7 @@ struct controller_impl { return bsp; } - std::future create_block_state_future( const block_id_type& id, const signed_block_ptr& b ) { + std::future create_block_state_future( const block_id_type& id, const signed_block_ptr& b ) { EOS_ASSERT( b, block_validate_exception, "null block" ); return post_async_task( thread_pool.get_executor(), [b, id, control=this]() { @@ -2227,7 +2223,7 @@ struct controller_impl { } // thread safe, expected to be called from thread other than the main thread - block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) { + block_state_legacy_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) { EOS_ASSERT( b, block_validate_exception, "null block" ); // no reason for a block_state if fork_db already knows about block @@ -2242,7 +2238,7 @@ struct controller_impl { } void push_block( controller::block_report& br, - const block_state_ptr& bsp, + const block_state_legacy_ptr& bsp, const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup ) { @@ -2262,15 +2258,13 @@ struct controller_impl { return; } - emit( self.pre_accepted_block, b ); - fork_db.add( bsp ); if (self.is_trusted_producer(b->producer)) { trusted_producer_light_validation = true; }; - emit( self.accepted_block_header, bsp ); + emit( self.accepted_block_header, std::tie(bsp->block, bsp->id) ); if( read_mode != db_read_mode::IRREVERSIBLE ) { maybe_switch_forks( br, fork_db.pending_head(), s, forked_branch_cb, trx_lookup ); @@ -2297,10 +2291,9 @@ struct controller_impl { return; } - emit( self.pre_accepted_block, b ); const bool skip_validate_signee = !conf.force_all_checks; - auto bsp = std::make_shared( + auto bsp = std::make_shared( *head, b, protocol_features.get_protocol_feature_set(), @@ -2315,7 +2308,7 @@ struct controller_impl { fork_db.add( bsp, true ); } - emit( self.accepted_block_header, bsp ); + emit( self.accepted_block_header, std::tie(bsp->block, bsp->id) ); controller::block_report br; if( s == controller::block_status::irreversible ) { @@ -2323,7 +2316,7 @@ struct controller_impl { // On replay, log_irreversible is not called and so no irreversible_block signal is emitted. // So emit it explicitly here. - emit( self.irreversible_block, bsp ); + emit( self.irreversible_block, std::tie(bsp->block, bsp->id) ); if (!self.skip_db_sessions(s)) { db.commit(bsp->block_num); @@ -2338,7 +2331,7 @@ struct controller_impl { } FC_LOG_AND_RETHROW( ) } - void maybe_switch_forks( controller::block_report& br, const block_state_ptr& new_head, controller::block_status s, + void maybe_switch_forks( controller::block_report& br, const block_state_legacy_ptr& new_head, controller::block_status s, const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup ) { bool head_changed = true; @@ -2452,7 +2445,7 @@ struct controller_impl { } void update_producers_authority() { - const auto& producers = pending->get_pending_block_header_state().active_schedule.producers; + const auto& producers = pending->get_pending_block_header_state_legacy().active_schedule.producers; auto update_permission = [&]( auto& permission, auto threshold ) { auto auth = authority( threshold, {}, {}); @@ -2728,7 +2721,7 @@ struct controller_impl { wasmif.code_block_num_last_used(code_hash, vm_type, vm_version, block_num); } - block_state_ptr fork_db_head() const; + block_state_legacy_ptr fork_db_head() const; }; /// controller_impl thread_local platform_timer controller_impl::timer; @@ -2914,7 +2907,7 @@ void controller::preactivate_feature( const digest_type& feature_digest, bool is } my->db.modify( pso, [&]( auto& ps ) { - ps.preactivated_protocol_features.push_back( feature_digest ); + ps.preactivated_protocol_features.emplace_back(feature_digest); } ); } @@ -2956,15 +2949,15 @@ void controller::start_block( block_timestamp_type when, bs, std::optional(), deadline ); } -block_state_ptr controller::finalize_block( block_report& br, const signer_callback_type& signer_callback ) { +block_state_legacy_ptr controller::finalize_block( block_report& br, const signer_callback_type& signer_callback ) { validate_db_available_size(); my->finalize_block(); auto& ab = std::get(my->pending->_block_stage); - auto bsp = std::make_shared( - std::move( ab._pending_block_header_state ), + auto bsp = std::make_shared( + std::move( ab._pending_block_header_state_legacy ), std::move( ab._unsigned_block ), std::move( ab._trx_metas ), my->protocol_features.get_protocol_feature_set(), @@ -2995,16 +2988,16 @@ boost::asio::io_context& controller::get_thread_pool() { return my->thread_pool.get_executor(); } -std::future controller::create_block_state_future( const block_id_type& id, const signed_block_ptr& b ) { +std::future controller::create_block_state_future( const block_id_type& id, const signed_block_ptr& b ) { return my->create_block_state_future( id, b ); } -block_state_ptr controller::create_block_state( const block_id_type& id, const signed_block_ptr& b ) const { +block_state_legacy_ptr controller::create_block_state( const block_id_type& id, const signed_block_ptr& b ) const { return my->create_block_state( id, b ); } void controller::push_block( controller::block_report& br, - const block_state_ptr& bsp, + const block_state_legacy_ptr& bsp, const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup ) { @@ -3092,11 +3085,11 @@ account_name controller::head_block_producer()const { const block_header& controller::head_block_header()const { return my->head->header; } -block_state_ptr controller::head_block_state()const { +block_state_legacy_ptr controller::head_block_state()const { return my->head; } -block_state_ptr controller_impl::fork_db_head() const { +block_state_legacy_ptr controller_impl::fork_db_head() const { if( read_mode == db_read_mode::IRREVERSIBLE ) { // When in IRREVERSIBLE mode fork_db blocks are marked valid when they become irreversible so that // fork_db.head() returns irreversible block @@ -3121,7 +3114,7 @@ block_timestamp_type controller::pending_block_timestamp()const { if( std::holds_alternative(my->pending->_block_stage) ) return std::get(my->pending->_block_stage)._block_state->header.timestamp; - return my->pending->get_pending_block_header_state().timestamp; + return my->pending->get_pending_block_header_state_legacy().timestamp; } time_point controller::pending_block_time()const { @@ -3134,7 +3127,7 @@ uint32_t controller::pending_block_num()const { if( std::holds_alternative(my->pending->_block_stage) ) return std::get(my->pending->_block_stage)._block_state->header.block_num(); - return my->pending->get_pending_block_header_state().block_num; + return my->pending->get_pending_block_header_state_legacy().block_num; } account_name controller::pending_block_producer()const { @@ -3143,7 +3136,7 @@ account_name controller::pending_block_producer()const { if( std::holds_alternative(my->pending->_block_stage) ) return std::get(my->pending->_block_stage)._block_state->header.producer; - return my->pending->get_pending_block_header_state().producer; + return my->pending->get_pending_block_header_state_legacy().producer; } const block_signing_authority& controller::pending_block_signing_authority()const { @@ -3152,7 +3145,7 @@ const block_signing_authority& controller::pending_block_signing_authority()cons if( std::holds_alternative(my->pending->_block_stage) ) return std::get(my->pending->_block_stage)._block_state->valid_block_signing_authority; - return my->pending->get_pending_block_header_state().valid_block_signing_authority; + return my->pending->get_pending_block_header_state_legacy().valid_block_signing_authority; } std::optional controller::pending_producer_block_id()const { @@ -3214,12 +3207,12 @@ std::optional controller::fetch_block_header_by_number( uin return my->blog.read_block_header_by_num(block_num); } FC_CAPTURE_AND_RETHROW( (block_num) ) } -block_state_ptr controller::fetch_block_state_by_id( block_id_type id )const { +block_state_legacy_ptr controller::fetch_block_state_by_id( block_id_type id )const { auto state = my->fork_db.get_block(id); return state; } -block_state_ptr controller::fetch_block_state_by_number( uint32_t block_num )const { try { +block_state_legacy_ptr controller::fetch_block_state_by_number( uint32_t block_num )const { try { return my->fork_db.search_on_branch( fork_db_head_block_id(), block_num ); } FC_CAPTURE_AND_RETHROW( (block_num) ) } @@ -3304,7 +3297,7 @@ int64_t controller::set_proposed_producers( vector producers my->db.modify( gpo, [&]( auto& gp ) { gp.proposed_schedule_block_num = cur_block_num; - gp.proposed_schedule = sch.to_shared(gp.proposed_schedule.producers.get_allocator()); + gp.proposed_schedule = sch; }); return version; } @@ -3316,7 +3309,7 @@ const producer_authority_schedule& controller::active_producers()const { if( std::holds_alternative(my->pending->_block_stage) ) return std::get(my->pending->_block_stage)._block_state->active_schedule; - return my->pending->get_pending_block_header_state().active_schedule; + return my->pending->get_pending_block_header_state_legacy().active_schedule; } const producer_authority_schedule& controller::pending_producers()const { @@ -3338,7 +3331,7 @@ const producer_authority_schedule& controller::pending_producers()const { if( bb._new_pending_producer_schedule ) return *bb._new_pending_producer_schedule; - return bb._pending_block_header_state.prev_pending_schedule.schedule; + return bb._pending_block_header_state_legacy.prev_pending_schedule.schedule; } std::optional controller::proposed_producers()const { diff --git a/libraries/chain/deep_mind.cpp b/libraries/chain/deep_mind.cpp index 0c677a3049..7d740235cd 100644 --- a/libraries/chain/deep_mind.cpp +++ b/libraries/chain/deep_mind.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ namespace eosio::chain { fc_dlog(_logger, "START_BLOCK ${block_num}", ("block_num", block_num)); } - void deep_mind_handler::on_accepted_block(const std::shared_ptr& bsp) + void deep_mind_handler::on_accepted_block(const std::shared_ptr& bsp) { auto packed_blk = fc::raw::pack(*bsp); diff --git a/libraries/chain/fork_database.cpp b/libraries/chain/fork_database.cpp index 9a7f863914..16d15a62c4 100644 --- a/libraries/chain/fork_database.cpp +++ b/libraries/chain/fork_database.cpp @@ -20,8 +20,8 @@ namespace eosio { namespace chain { const uint32_t fork_database::min_supported_version = 1; const uint32_t fork_database::max_supported_version = 1; - // work around block_state::is_valid being private - inline bool block_state_is_valid( const block_state& bs ) { + // work around block_state_legacy::is_valid being private + inline bool block_state_is_valid( const block_state_legacy& bs ) { return bs.is_valid(); } @@ -34,16 +34,16 @@ namespace eosio { namespace chain { struct by_lib_block_num; struct by_prev; typedef multi_index_container< - block_state_ptr, + block_state_legacy_ptr, indexed_by< - hashed_unique< tag, member, std::hash>, - ordered_non_unique< tag, const_mem_fun >, + hashed_unique< tag, member, std::hash>, + ordered_non_unique< tag, const_mem_fun >, ordered_unique< tag, - composite_key< block_state, - global_fun, - member, - member, - member + composite_key< block_state_legacy, + global_fun, + member, + member, + member >, composite_key_compare< std::greater, @@ -55,7 +55,7 @@ namespace eosio { namespace chain { > > fork_multi_index_type; - bool first_preferred( const block_header_state& lhs, const block_header_state& rhs ) { + bool first_preferred( const block_header_state_legacy& lhs, const block_header_state_legacy& rhs ) { return std::tie( lhs.dpos_irreversible_blocknum, lhs.block_num ) > std::tie( rhs.dpos_irreversible_blocknum, rhs.block_num ); } @@ -65,11 +65,11 @@ namespace eosio { namespace chain { :datadir(data_dir) {} - std::shared_mutex mtx; - fork_multi_index_type index; - block_state_ptr root; // Only uses the block_header_state portion - block_state_ptr head; - std::filesystem::path datadir; + std::shared_mutex mtx; + fork_multi_index_type index; + block_state_legacy_ptr root; // Only uses the block_header_state_legacy portion + block_state_legacy_ptr head; + std::filesystem::path datadir; void open_impl( const std::function&, @@ -77,19 +77,19 @@ namespace eosio { namespace chain { void close_impl(); - block_header_state_ptr get_block_header_impl( const block_id_type& id )const; - block_state_ptr get_block_impl( const block_id_type& id )const; - void reset_impl( const block_header_state& root_bhs ); + block_header_state_legacy_ptr get_block_header_impl( const block_id_type& id )const; + block_state_legacy_ptr get_block_impl( const block_id_type& id )const; + void reset_impl( const block_header_state_legacy& root_bhs ); void rollback_head_to_root_impl(); void advance_root_impl( const block_id_type& id ); void remove_impl( const block_id_type& id ); branch_type fetch_branch_impl( const block_id_type& h, uint32_t trim_after_block_num )const; - block_state_ptr search_on_branch_impl( const block_id_type& h, uint32_t block_num )const; + block_state_legacy_ptr search_on_branch_impl( const block_id_type& h, uint32_t block_num )const; pair fetch_branch_from_impl( const block_id_type& first, const block_id_type& second )const; - void mark_valid_impl( const block_state_ptr& h ); + void mark_valid_impl( const block_state_legacy_ptr& h ); - void add_impl( const block_state_ptr& n, + void add_impl( const block_state_legacy_ptr& n, bool ignore_duplicate, bool validate, const std::function&, @@ -148,17 +148,17 @@ namespace eosio { namespace chain { ("max", fork_database::max_supported_version) ); - block_header_state bhs; + block_header_state_legacy bhs; fc::raw::unpack( ds, bhs ); reset_impl( bhs ); unsigned_int size; fc::raw::unpack( ds, size ); for( uint32_t i = 0, n = size.value; i < n; ++i ) { - block_state s; + block_state_legacy s; fc::raw::unpack( ds, s ); // do not populate transaction_metadatas, they will be created as needed in apply_block with appropriate key recovery s.header_exts = s.block->validate_and_extract_header_extensions(); - add_impl( std::make_shared( std::move( s ) ), false, true, validator ); + add_impl( std::make_shared( std::move( s ) ), false, true, validator ); } block_id_type head_id; fc::raw::unpack( ds, head_id ); @@ -207,7 +207,7 @@ namespace eosio { namespace chain { std::ofstream out( fork_db_dat.generic_string().c_str(), std::ios::out | std::ios::binary | std::ofstream::trunc ); fc::raw::pack( out, fork_database::magic_number ); fc::raw::pack( out, fork_database::max_supported_version ); // write out current version which is always max_supported_version - fc::raw::pack( out, *static_cast(&*root) ); + fc::raw::pack( out, *static_cast(&*root) ); uint32_t num_blocks_in_fork_db = index.size(); fc::raw::pack( out, unsigned_int{num_blocks_in_fork_db} ); @@ -260,15 +260,15 @@ namespace eosio { namespace chain { my->close_impl(); } - void fork_database::reset( const block_header_state& root_bhs ) { + void fork_database::reset( const block_header_state_legacy& root_bhs ) { std::lock_guard g( my->mtx ); my->reset_impl(root_bhs); } - void fork_database_impl::reset_impl( const block_header_state& root_bhs ) { + void fork_database_impl::reset_impl( const block_header_state_legacy& root_bhs ) { index.clear(); - root = std::make_shared(); - static_cast(*root) = root_bhs; + root = std::make_shared(); + static_cast(*root) = root_bhs; root->validated = true; head = root; } @@ -282,7 +282,7 @@ namespace eosio { namespace chain { auto& by_id_idx = index.get(); auto itr = by_id_idx.begin(); while (itr != by_id_idx.end()) { - by_id_idx.modify( itr, [&]( block_state_ptr& bsp ) { + by_id_idx.modify( itr, [&]( block_state_legacy_ptr& bsp ) { bsp->validated = false; } ); ++itr; @@ -328,12 +328,12 @@ namespace eosio { namespace chain { root = new_root; } - block_header_state_ptr fork_database::get_block_header( const block_id_type& id )const { + block_header_state_legacy_ptr fork_database::get_block_header( const block_id_type& id )const { std::shared_lock g( my->mtx ); return my->get_block_header_impl( id ); } - block_header_state_ptr fork_database_impl::get_block_header_impl( const block_id_type& id )const { + block_header_state_legacy_ptr fork_database_impl::get_block_header_impl( const block_id_type& id )const { if( root->id == id ) { return root; } @@ -342,10 +342,10 @@ namespace eosio { namespace chain { if( itr != index.end() ) return *itr; - return block_header_state_ptr(); + return block_header_state_legacy_ptr(); } - void fork_database_impl::add_impl( const block_state_ptr& n, + void fork_database_impl::add_impl( const block_state_legacy_ptr& n, bool ignore_duplicate, bool validate, const std::function&, @@ -382,7 +382,7 @@ namespace eosio { namespace chain { } } - void fork_database::add( const block_state_ptr& n, bool ignore_duplicate ) { + void fork_database::add( const block_state_legacy_ptr& n, bool ignore_duplicate ) { std::lock_guard g( my->mtx ); my->add_impl( n, ignore_duplicate, false, []( block_timestamp_type timestamp, @@ -392,17 +392,17 @@ namespace eosio { namespace chain { ); } - block_state_ptr fork_database::root()const { + block_state_legacy_ptr fork_database::root()const { std::shared_lock g( my->mtx ); return my->root; } - block_state_ptr fork_database::head()const { + block_state_legacy_ptr fork_database::head()const { std::shared_lock g( my->mtx ); return my->head; } - block_state_ptr fork_database::pending_head()const { + block_state_legacy_ptr fork_database::pending_head()const { std::shared_lock g( my->mtx ); const auto& indx = my->index.get(); @@ -430,12 +430,12 @@ namespace eosio { namespace chain { return result; } - block_state_ptr fork_database::search_on_branch( const block_id_type& h, uint32_t block_num )const { + block_state_legacy_ptr fork_database::search_on_branch( const block_id_type& h, uint32_t block_num )const { std::shared_lock g( my->mtx ); return my->search_on_branch_impl( h, block_num ); } - block_state_ptr fork_database_impl::search_on_branch_impl( const block_id_type& h, uint32_t block_num )const { + block_state_legacy_ptr fork_database_impl::search_on_branch_impl( const block_id_type& h, uint32_t block_num )const { for( auto s = get_block_impl(h); s; s = get_block_impl( s->header.previous ) ) { if( s->block_num == block_num ) return s; @@ -540,12 +540,12 @@ namespace eosio { namespace chain { } } - void fork_database::mark_valid( const block_state_ptr& h ) { + void fork_database::mark_valid( const block_state_legacy_ptr& h ) { std::lock_guard g( my->mtx ); my->mark_valid_impl( h ); } - void fork_database_impl::mark_valid_impl( const block_state_ptr& h ) { + void fork_database_impl::mark_valid_impl( const block_state_legacy_ptr& h ) { if( h->validated ) return; auto& by_id_idx = index.get(); @@ -555,7 +555,7 @@ namespace eosio { namespace chain { "block state not in fork database; cannot mark as valid", ("id", h->id) ); - by_id_idx.modify( itr, []( block_state_ptr& bsp ) { + by_id_idx.modify( itr, []( block_state_legacy_ptr& bsp ) { bsp->validated = true; } ); @@ -565,16 +565,16 @@ namespace eosio { namespace chain { } } - block_state_ptr fork_database::get_block(const block_id_type& id)const { + block_state_legacy_ptr fork_database::get_block(const block_id_type& id)const { std::shared_lock g( my->mtx ); return my->get_block_impl(id); } - block_state_ptr fork_database_impl::get_block_impl(const block_id_type& id)const { + block_state_legacy_ptr fork_database_impl::get_block_impl(const block_id_type& id)const { auto itr = index.find( id ); if( itr != index.end() ) return *itr; - return block_state_ptr(); + return block_state_legacy_ptr(); } } } /// eosio::chain diff --git a/libraries/chain/include/eosio/chain/authority.hpp b/libraries/chain/include/eosio/chain/authority.hpp index a168aaa105..11ae30feb4 100644 --- a/libraries/chain/include/eosio/chain/authority.hpp +++ b/libraries/chain/include/eosio/chain/authority.hpp @@ -116,20 +116,19 @@ struct shared_key_weight { return key_weight{key.to_public_key(), weight}; } - static shared_key_weight convert(chainbase::allocator allocator, const key_weight& k) { - return std::visit(overloaded { - [&](const auto& k1r1) { - return shared_key_weight(k1r1, k.weight); + shared_key_weight(const key_weight& k) : key(fc::ecc::public_key_shim()), weight(k.weight) { + std::visit(overloaded { + [&](const T& k1r1) { + key.pubkey.emplace(k1r1); }, [&](const fc::crypto::webauthn::public_key& wa) { size_t psz = fc::raw::pack_size(wa); - shared_string wa_ss(std::move(allocator)); - wa_ss.resize_and_fill( psz, [&wa]( char* data, std::size_t sz ) { - fc::datastream ds(data, sz); - fc::raw::pack(ds, wa); - }); - - return shared_key_weight(std::move(wa_ss), k.weight); + // create a shared_string in the pubkey that we will write (using pack) directly into. + key.pubkey.emplace(psz, boost::container::default_init_t()); + auto& s = std::get(key.pubkey); + assert(s.mutable_data() && s.size() == psz); + fc::datastream ds(s.mutable_data(), psz); + fc::raw::pack(ds, wa); } }, k.key._storage); } @@ -221,18 +220,37 @@ struct authority { struct shared_authority { - explicit shared_authority( chainbase::allocator alloc ) - :keys(alloc),accounts(alloc),waits(alloc){} - - shared_authority& operator=(const authority& a) { - threshold = a.threshold; - keys.clear(); - keys.reserve(a.keys.size()); - for(const key_weight& k : a.keys) { - keys.emplace_back(shared_key_weight::convert(keys.get_allocator(), k)); - } - accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator()); - waits = decltype(waits)(a.waits.begin(), a.waits.end(), waits.get_allocator()); + explicit shared_authority() = default; + + shared_authority(const authority& auth) : + threshold(auth.threshold), + keys(auth.keys), + accounts(auth.accounts), + waits(auth.waits) + { + } + + shared_authority(authority&& auth) : + threshold(auth.threshold), + keys(std::move(auth.keys)), + accounts(std::move(auth.accounts)), + waits(std::move(auth.waits)) + { + } + + shared_authority& operator=(const authority& auth) { + threshold = auth.threshold; + keys = auth.keys; + accounts = auth.accounts; + waits = auth.waits; + return *this; + } + + shared_authority& operator=(authority&& auth) { + threshold = auth.threshold; + keys = std::move(auth.keys); + accounts = std::move(auth.accounts); + waits = std::move(auth.waits); return *this; } diff --git a/libraries/chain/include/eosio/chain/authority_checker.hpp b/libraries/chain/include/eosio/chain/authority_checker.hpp index ccda160c99..a0d9f2d154 100644 --- a/libraries/chain/include/eosio/chain/authority_checker.hpp +++ b/libraries/chain/include/eosio/chain/authority_checker.hpp @@ -28,8 +28,8 @@ namespace detail { * then determine whether that list of keys is sufficient to satisfy the authority. This class takes a list of keys and * provides the @ref satisfied method to determine whether that list of keys satisfies a provided authority. * - * @tparam F A callable which takes a single argument of type @ref AccountPermission and returns the corresponding - * authority + * @tparam F A callable which takes a single argument of type @ref AccountPermission and returns a pointer to + * the corresponding authority if it exists, or a nullptr. */ template class authority_checker { @@ -225,19 +225,18 @@ namespace detail { bool r = false; typename permission_cache_type::iterator itr = cached_permissions.end(); - bool propagate_error = false; + std::invoke_result_t auth = nullptr; try { - auto&& auth = checker.permission_to_authority( permission.permission ); - propagate_error = true; - auto res = cached_permissions.emplace( permission.permission, being_evaluated ); - itr = res.first; - r = checker.satisfied( std::forward(auth), cached_permissions, recursion_depth + 1 ); - } catch( const permission_query_exception& ) { - if( propagate_error ) - throw; - else - return total_weight; // if the permission doesn't exist, continue without it + auth = checker.permission_to_authority( permission.permission ); } + catch( const permission_query_exception& ) {} + //permission was either invalid (threw permission_query_exception), or wasn't found + if(!auth) + return total_weight; + + auto res = cached_permissions.emplace( permission.permission, being_evaluated ); + itr = res.first; + r = checker.satisfied( *auth, cached_permissions, recursion_depth + 1 ); if( r ) { total_weight += permission.weight; diff --git a/libraries/chain/include/eosio/chain/block_header_state.hpp b/libraries/chain/include/eosio/chain/block_header_state_legacy.hpp similarity index 71% rename from libraries/chain/include/eosio/chain/block_header_state.hpp rename to libraries/chain/include/eosio/chain/block_header_state_legacy.hpp index 5b4d64ce48..7e4a5e8abc 100644 --- a/libraries/chain/include/eosio/chain/block_header_state.hpp +++ b/libraries/chain/include/eosio/chain/block_header_state_legacy.hpp @@ -24,7 +24,7 @@ namespace legacy { producer_schedule_type schedule; }; - /// from block_header_state_common + /// from block_header_state_legacy_common uint32_t block_num = 0; uint32_t dpos_proposed_irreversible_blocknum = 0; uint32_t dpos_irreversible_blocknum = 0; @@ -35,7 +35,7 @@ namespace legacy { public_key_type block_signing_key; vector confirm_count; - // from block_header_state + // from block_header_state_legacy block_id_type id; signed_block_header header; schedule_info pending_schedule; @@ -45,10 +45,10 @@ namespace legacy { using signer_callback_type = std::function(const digest_type&)>; -struct block_header_state; +struct block_header_state_legacy; namespace detail { - struct block_header_state_common { + struct block_header_state_legacy_common { uint32_t block_num = 0; uint32_t dpos_proposed_irreversible_blocknum = 0; uint32_t dpos_irreversible_blocknum = 0; @@ -71,7 +71,7 @@ namespace detail { builtin_protocol_feature_t feature_codename ); } -struct pending_block_header_state : public detail::block_header_state_common { +struct pending_block_header_state_legacy : public detail::block_header_state_legacy_common { protocol_feature_activation_set_ptr prev_activated_protocol_features; detail::schedule_info prev_pending_schedule; bool was_pending_promoted = false; @@ -87,34 +87,34 @@ struct pending_block_header_state : public detail::block_header_state_common { vector&& new_protocol_feature_activations, const protocol_feature_set& pfs)const; - block_header_state finish_next( const signed_block_header& h, - vector&& additional_signatures, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - bool skip_validate_signee = false )&&; - - block_header_state finish_next( signed_block_header& h, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - const signer_callback_type& signer )&&; + block_header_state_legacy finish_next( const signed_block_header& h, + vector&& additional_signatures, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + bool skip_validate_signee = false )&&; + + block_header_state_legacy finish_next( signed_block_header& h, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + const signer_callback_type& signer )&&; protected: - block_header_state _finish_next( const signed_block_header& h, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator )&&; + block_header_state_legacy _finish_next( const signed_block_header& h, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator )&&; }; /** - * @struct block_header_state + * @struct block_header_state_legacy * @brief defines the minimum state necessary to validate transaction headers */ -struct block_header_state : public detail::block_header_state_common { +struct block_header_state_legacy : public detail::block_header_state_legacy_common { block_id_type id; signed_block_header header; detail::schedule_info pending_schedule; @@ -125,23 +125,23 @@ struct block_header_state : public detail::block_header_state_common { /// duplication of work flat_multimap header_exts; - block_header_state() = default; + block_header_state_legacy() = default; - explicit block_header_state( detail::block_header_state_common&& base ) - :detail::block_header_state_common( std::move(base) ) + explicit block_header_state_legacy( detail::block_header_state_legacy_common&& base ) + :detail::block_header_state_legacy_common( std::move(base) ) {} - explicit block_header_state( legacy::snapshot_block_header_state_v2&& snapshot ); + explicit block_header_state_legacy( legacy::snapshot_block_header_state_v2&& snapshot ); - pending_block_header_state next( block_timestamp_type when, uint16_t num_prev_blocks_to_confirm )const; + pending_block_header_state_legacy next( block_timestamp_type when, uint16_t num_prev_blocks_to_confirm )const; - block_header_state next( const signed_block_header& h, - vector&& additional_signatures, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - bool skip_validate_signee = false )const; + block_header_state_legacy next( const signed_block_header& h, + vector&& additional_signatures, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + bool skip_validate_signee = false )const; bool has_pending_producers()const { return pending_schedule.schedule.producers.size(); } uint32_t calc_dpos_last_irreversible( account_name producer_of_next_block )const; @@ -155,11 +155,11 @@ struct block_header_state : public detail::block_header_state_common { const vector& get_new_protocol_feature_activations()const; }; -using block_header_state_ptr = std::shared_ptr; +using block_header_state_legacy_ptr = std::shared_ptr; } } /// namespace eosio::chain -FC_REFLECT( eosio::chain::detail::block_header_state_common, +FC_REFLECT( eosio::chain::detail::block_header_state_legacy_common, (block_num) (dpos_proposed_irreversible_blocknum) (dpos_irreversible_blocknum) @@ -177,7 +177,7 @@ FC_REFLECT( eosio::chain::detail::schedule_info, (schedule) ) -FC_REFLECT_DERIVED( eosio::chain::block_header_state, (eosio::chain::detail::block_header_state_common), +FC_REFLECT_DERIVED( eosio::chain::block_header_state_legacy, (eosio::chain::detail::block_header_state_legacy_common), (id) (header) (pending_schedule) diff --git a/libraries/chain/include/eosio/chain/block_state.hpp b/libraries/chain/include/eosio/chain/block_state.hpp deleted file mode 100644 index 4772094739..0000000000 --- a/libraries/chain/include/eosio/chain/block_state.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace eosio { namespace chain { - - struct block_state : public block_header_state { - block_state( const block_header_state& prev, - signed_block_ptr b, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - bool skip_validate_signee - ); - - block_state( pending_block_header_state&& cur, - signed_block_ptr&& b, // unsigned block - deque&& trx_metas, - const protocol_feature_set& pfs, - const std::function&, - const vector& )>& validator, - const signer_callback_type& signer - ); - - block_state() = default; - - - signed_block_ptr block; - - private: // internal use only, not thread safe - friend struct fc::reflector; - friend bool block_state_is_valid( const block_state& ); // work-around for multi-index access - friend struct controller_impl; - friend class fork_database; - friend struct fork_database_impl; - friend class unapplied_transaction_queue; - friend struct pending_state; - - bool is_valid()const { return validated; } - bool is_pub_keys_recovered()const { return _pub_keys_recovered; } - - deque extract_trxs_metas() { - _pub_keys_recovered = false; - auto result = std::move( _cached_trxs ); - _cached_trxs.clear(); - return result; - } - void set_trxs_metas( deque&& trxs_metas, bool keys_recovered ) { - _pub_keys_recovered = keys_recovered; - _cached_trxs = std::move( trxs_metas ); - } - const deque& trxs_metas()const { return _cached_trxs; } - - bool validated = false; - - bool _pub_keys_recovered = false; - /// this data is redundant with the data stored in block, but facilitates - /// recapturing transactions when we pop a block - deque _cached_trxs; - }; - - using block_state_ptr = std::shared_ptr; - using branch_type = deque; - -} } /// namespace eosio::chain - -FC_REFLECT_DERIVED( eosio::chain::block_state, (eosio::chain::block_header_state), (block)(validated) ) diff --git a/libraries/chain/include/eosio/chain/block_state_legacy.hpp b/libraries/chain/include/eosio/chain/block_state_legacy.hpp new file mode 100644 index 0000000000..b56bb7f990 --- /dev/null +++ b/libraries/chain/include/eosio/chain/block_state_legacy.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include + +namespace eosio { namespace chain { + + struct block_state_legacy : public block_header_state_legacy { + block_state_legacy( const block_header_state_legacy& prev, + signed_block_ptr b, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + bool skip_validate_signee + ); + + block_state_legacy( pending_block_header_state_legacy&& cur, + signed_block_ptr&& b, // unsigned block + deque&& trx_metas, + const protocol_feature_set& pfs, + const std::function&, + const vector& )>& validator, + const signer_callback_type& signer + ); + + block_state_legacy() = default; + + + signed_block_ptr block; + + private: // internal use only, not thread safe + friend struct fc::reflector; + friend bool block_state_is_valid( const block_state_legacy& ); // work-around for multi-index access + friend struct controller_impl; + friend class fork_database; + friend struct fork_database_impl; + friend class unapplied_transaction_queue; + friend struct pending_state; + + bool is_valid()const { return validated; } + bool is_pub_keys_recovered()const { return _pub_keys_recovered; } + + deque extract_trxs_metas() { + _pub_keys_recovered = false; + auto result = std::move( _cached_trxs ); + _cached_trxs.clear(); + return result; + } + void set_trxs_metas( deque&& trxs_metas, bool keys_recovered ) { + _pub_keys_recovered = keys_recovered; + _cached_trxs = std::move( trxs_metas ); + } + const deque& trxs_metas()const { return _cached_trxs; } + + bool validated = false; + + bool _pub_keys_recovered = false; + /// this data is redundant with the data stored in block, but facilitates + /// recapturing transactions when we pop a block + deque _cached_trxs; + }; + + using block_state_legacy_ptr = std::shared_ptr; + using branch_type = deque; + +} } /// namespace eosio::chain + +FC_REFLECT_DERIVED( eosio::chain::block_state_legacy, (eosio::chain::block_header_state_legacy), (block)(validated) ) diff --git a/libraries/chain/include/eosio/chain/chainbase_environment.hpp b/libraries/chain/include/eosio/chain/chainbase_environment.hpp new file mode 100644 index 0000000000..9f858655fb --- /dev/null +++ b/libraries/chain/include/eosio/chain/chainbase_environment.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +// reflect chainbase::environment for --print-build-info option +FC_REFLECT_ENUM(chainbase::environment::os_t, + (OS_LINUX) (OS_MACOS) (OS_WINDOWS) (OS_OTHER)) +FC_REFLECT_ENUM(chainbase::environment::arch_t, + (ARCH_X86_64) (ARCH_ARM) (ARCH_RISCV) (ARCH_OTHER)) + +namespace fc { + +void to_variant(const chainbase::environment& bi, variant& v) { + // the variant conversion ultimately binds a reference to each member, but chainbase::environment is packed making + // a reference to an unaligned variable UB. The boost_version is the only offender + unsigned aligned_boost_version = bi.boost_version; + v = fc::mutable_variant_object()("debug", bi.debug) + ("os", bi.os) + ("arch", bi.arch) + ("boost_version", aligned_boost_version) + ("compiler", bi.compiler); + +} + +} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index b601b2f6c4..50417aa31f 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include #include @@ -44,6 +44,8 @@ namespace eosio { namespace chain { // lookup transaction_metadata via supplied function to avoid re-creation using trx_meta_cache_lookup = std::function; + using block_signal_params = std::tuple; + class fork_database; enum class db_read_mode { @@ -161,14 +163,14 @@ namespace eosio { namespace chain { fc::microseconds total_time{}; }; - block_state_ptr finalize_block( block_report& br, const signer_callback_type& signer_callback ); + block_state_legacy_ptr finalize_block( block_report& br, const signer_callback_type& signer_callback ); void sign_block( const signer_callback_type& signer_callback ); void commit_block(); // thread-safe - std::future create_block_state_future( const block_id_type& id, const signed_block_ptr& b ); + std::future create_block_state_future( const block_id_type& id, const signed_block_ptr& b ); // thread-safe - block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) const; + block_state_legacy_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) const; /** * @param br returns statistics for block @@ -177,7 +179,7 @@ namespace eosio { namespace chain { * @param trx_lookup user provided lookup function for externally cached transaction_metadata */ void push_block( block_report& br, - const block_state_ptr& bsp, + const block_state_legacy_ptr& bsp, const forked_branch_callback& cb, const trx_meta_cache_lookup& trx_lookup ); @@ -219,7 +221,7 @@ namespace eosio { namespace chain { block_id_type head_block_id()const; account_name head_block_producer()const; const block_header& head_block_header()const; - block_state_ptr head_block_state()const; + block_state_legacy_ptr head_block_state()const; uint32_t fork_db_head_block_num()const; block_id_type fork_db_head_block_id()const; @@ -247,10 +249,10 @@ namespace eosio { namespace chain { std::optional fetch_block_header_by_number( uint32_t block_num )const; // thread-safe std::optional fetch_block_header_by_id( const block_id_type& id )const; - // return block_state from forkdb, thread-safe - block_state_ptr fetch_block_state_by_number( uint32_t block_num )const; - // return block_state from forkdb, thread-safe - block_state_ptr fetch_block_state_by_id( block_id_type id )const; + // return block_state_legacy from forkdb, thread-safe + block_state_legacy_ptr fetch_block_state_by_number( uint32_t block_num )const; + // return block_state_legacy from forkdb, thread-safe + block_state_legacy_ptr fetch_block_state_by_id( block_id_type id )const; // thread-safe block_id_type get_block_id_for_num( uint32_t block_num )const; @@ -328,24 +330,11 @@ namespace eosio { namespace chain { static std::optional convert_exception_to_error_code( const fc::exception& e ); - signal block_start; // block_num - signal pre_accepted_block; - signal accepted_block_header; - signal accepted_block; - signal irreversible_block; - signal accepted_transaction; + signal block_start; + signal accepted_block_header; + signal accepted_block; + signal irreversible_block; signal)> applied_transaction; - signal bad_alloc; - - /* - signal pre_apply_block; - signal post_apply_block; - signal abort_apply_block; - signal pre_apply_transaction; - signal post_apply_transaction; - signal pre_apply_action; - signal post_apply_action; - */ const apply_handler* find_apply_handler( account_name contract, scope_name scope, action_name act )const; wasm_interface& get_wasm_interface(); diff --git a/libraries/chain/include/eosio/chain/database_utils.hpp b/libraries/chain/include/eosio/chain/database_utils.hpp index e039d12198..9f4859d06b 100644 --- a/libraries/chain/include/eosio/chain/database_utils.hpp +++ b/libraries/chain/include/eosio/chain/database_utils.hpp @@ -4,7 +4,7 @@ #include #include -namespace eosio { namespace chain { +namespace eosio::chain { template class index_set; @@ -80,18 +80,6 @@ namespace eosio { namespace chain { } }; - template - DataStream& operator << ( DataStream& ds, const shared_blob& b ) { - fc::raw::pack(ds, static_cast(b)); - return ds; - } - - template - DataStream& operator >> ( DataStream& ds, shared_blob& b ) { - fc::raw::unpack(ds, static_cast(b)); - return ds; - } - namespace detail { struct snapshot_key_value_object { template @@ -127,7 +115,7 @@ namespace detail { }; } -} } +} namespace fc { @@ -208,7 +196,7 @@ namespace fc { void from_variant( const variant& v, eosio::chain::shared_string& s ) { std::string _s; from_variant(v, _s); - s = eosio::chain::shared_string(_s.begin(), _s.end(), s.get_allocator()); + s = _s; } inline @@ -219,7 +207,7 @@ namespace fc { inline void from_variant( const variant& v, eosio::chain::shared_blob& b ) { std::vector b64 = base64_decode(v.as_string()); - b = eosio::chain::shared_blob(b64.begin(), b64.end(), b.get_allocator()); + b = std::string_view(b64.data(), b64.size()); } template @@ -231,7 +219,7 @@ namespace fc { void from_variant( const variant& v, eosio::chain::shared_vector& sv ) { std::vector _v; from_variant(v, _v); - sv = eosio::chain::shared_vector(_v.begin(), _v.end(), sv.get_allocator()); + sv = v; } inline @@ -262,6 +250,65 @@ namespace chainbase { fc::raw::unpack(ds, oid._id); return ds; } + + // chainbase::shared_cow_string + // ---------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_string& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack(s, fc::unsigned_int((uint32_t)v.size())); + if( v.size() ) + s.write((const char*)v.data(), v.size()); + return s; + } + + template + inline Stream& operator>>(Stream& s, chainbase::shared_cow_string& v) { + fc::unsigned_int sz; + fc::raw::unpack(s, sz); + FC_ASSERT(sz.value <= MAX_SIZE_OF_BYTE_ARRAYS); + if (sz) { + v.resize_and_fill(sz, [&](char* buf, std::size_t sz) { + s.read(buf, sz); + }); + } + return s; + } + + // chainbase::shared_cow_vector + // ---------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_vector& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); + for (const auto& el : v) + fc::raw::pack(s, el); + return s; + } + + template + inline Stream& operator>>(Stream& s, chainbase::shared_cow_vector& v) { + fc::unsigned_int size; + fc::raw::unpack( s, size ); + FC_ASSERT(size.value <= MAX_NUM_ARRAY_ELEMENTS); + FC_ASSERT(v.size() == 0); + v.clear_and_construct(size.value, 0, [&](auto* dest, std::size_t i) { + new (dest) T(); // unpack expects a constructed variable + fc::raw::unpack(s, *dest); + }); + return s; + } + + // chainbase::shared_cow_vector + // ---------------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_vector& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); + if( v.size() ) + s.write((const char*)v.data(), v.size()); + return s; + } } // overloads for softfloat packing diff --git a/libraries/chain/include/eosio/chain/deep_mind.hpp b/libraries/chain/include/eosio/chain/deep_mind.hpp index 6ea659e5e3..ba630440a4 100644 --- a/libraries/chain/include/eosio/chain/deep_mind.hpp +++ b/libraries/chain/include/eosio/chain/deep_mind.hpp @@ -11,7 +11,7 @@ class generated_transaction_object; class table_id_object; struct key_value_object; class permission_object; -struct block_state; +struct block_state_legacy; struct protocol_feature; struct signed_transaction; struct packed_transaction; @@ -56,7 +56,7 @@ class deep_mind_handler void on_startup(chainbase::database& db, uint32_t head_block_num); void on_start_block(uint32_t block_num); - void on_accepted_block(const std::shared_ptr& bsp); + void on_accepted_block(const std::shared_ptr& bsp); void on_switch_forks(const block_id_type& old_head, const block_id_type& new_head); void on_onerror(const signed_transaction& etrx); void on_onblock(const signed_transaction& trx); diff --git a/libraries/chain/include/eosio/chain/fork_database.hpp b/libraries/chain/include/eosio/chain/fork_database.hpp index 56cf963fa2..2367631096 100644 --- a/libraries/chain/include/eosio/chain/fork_database.hpp +++ b/libraries/chain/include/eosio/chain/fork_database.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include namespace eosio { namespace chain { @@ -30,14 +30,14 @@ namespace eosio { namespace chain { const vector& )>& validator ); void close(); - block_header_state_ptr get_block_header( const block_id_type& id )const; - block_state_ptr get_block( const block_id_type& id )const; + block_header_state_legacy_ptr get_block_header( const block_id_type& id )const; + block_state_legacy_ptr get_block( const block_id_type& id )const; /** * Purges any existing blocks from the fork database and resets the root block_header_state to the provided value. * The head will also be reset to point to the root. */ - void reset( const block_header_state& root_bhs ); + void reset( const block_header_state_legacy& root_bhs ); /** * Removes validated flag from all blocks in fork database and resets head to point to the root. @@ -53,13 +53,13 @@ namespace eosio { namespace chain { * Add block state to fork database. * Must link to existing block in fork database or the root. */ - void add( const block_state_ptr& next_block, bool ignore_duplicate = false ); + void add( const block_state_legacy_ptr& next_block, bool ignore_duplicate = false ); void remove( const block_id_type& id ); - block_state_ptr root()const; - block_state_ptr head()const; - block_state_ptr pending_head()const; + block_state_legacy_ptr root()const; + block_state_legacy_ptr head()const; + block_state_legacy_ptr pending_head()const; /** * Returns the sequence of block states resulting from trimming the branch from the @@ -76,7 +76,7 @@ namespace eosio { namespace chain { * Returns the block state with a block number of `block_num` that is on the branch that * contains a block with an id of`h`, or the empty shared pointer if no such block can be found. */ - block_state_ptr search_on_branch( const block_id_type& h, uint32_t block_num )const; + block_state_legacy_ptr search_on_branch( const block_id_type& h, uint32_t block_num )const; /** * Given two head blocks, return two branches of the fork graph that @@ -86,7 +86,7 @@ namespace eosio { namespace chain { const block_id_type& second )const; - void mark_valid( const block_state_ptr& h ); + void mark_valid( const block_state_legacy_ptr& h ); static const uint32_t magic_number; diff --git a/libraries/chain/include/eosio/chain/global_property_object.hpp b/libraries/chain/include/eosio/chain/global_property_object.hpp index 7b7497e34e..24180fad6a 100644 --- a/libraries/chain/include/eosio/chain/global_property_object.hpp +++ b/libraries/chain/include/eosio/chain/global_property_object.hpp @@ -75,7 +75,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v2& legacy, const chain_id_type& chain_id_val, const kv_database_config& kv_config_val, const wasm_config& wasm_config_val ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = producer_authority_schedule(legacy.proposed_schedule).to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = producer_authority_schedule(legacy.proposed_schedule); configuration = legacy.configuration; chain_id = chain_id_val; kv_configuration = kv_config_val; @@ -84,7 +84,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v3& legacy, const kv_database_config& kv_config_val, const wasm_config& wasm_config_val ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = legacy.proposed_schedule.to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = legacy.proposed_schedule; configuration = legacy.configuration; chain_id = legacy.chain_id; kv_configuration = kv_config_val; @@ -93,7 +93,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v4& legacy ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = legacy.proposed_schedule.to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = legacy.proposed_schedule; configuration = legacy.configuration; chain_id = legacy.chain_id; kv_configuration = legacy.kv_configuration; @@ -132,7 +132,7 @@ namespace eosio { namespace chain { static void from_snapshot_row( snapshot_global_property_object&& row, global_property_object& value, chainbase::database& ) { value.proposed_schedule_block_num = row.proposed_schedule_block_num; - value.proposed_schedule = row.proposed_schedule.to_shared(value.proposed_schedule.producers.get_allocator()); + value.proposed_schedule = row.proposed_schedule; value.configuration = row.configuration; value.chain_id = row.chain_id; value.kv_configuration = row.kv_configuration; diff --git a/libraries/chain/include/eosio/chain/incremental_merkle.hpp b/libraries/chain/include/eosio/chain/incremental_merkle.hpp index 0a84d076f5..68b4348e9d 100644 --- a/libraries/chain/include/eosio/chain/incremental_merkle.hpp +++ b/libraries/chain/include/eosio/chain/incremental_merkle.hpp @@ -2,53 +2,12 @@ #include #include #include +#include -namespace eosio { namespace chain { +namespace eosio::chain { namespace detail { -/** - * given an unsigned integral number return the smallest - * power-of-2 which is greater than or equal to the given number - * - * @param value - an unsigned integral - * @return - the minimum power-of-2 which is >= value - */ -constexpr uint64_t next_power_of_2(uint64_t value) { - value -= 1; - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value |= value >> 32; - value += 1; - return value; -} - -/** - * Given a power-of-2 (assumed correct) return the number of leading zeros - * - * This is a classic count-leading-zeros in parallel without the necessary - * math to make it safe for anything that is not already a power-of-2 - * - * @param value - and integral power-of-2 - * @return the number of leading zeros - */ -constexpr int clz_power_2(uint64_t value) { - int lz = 64; - - if (value) lz--; - if (value & 0x00000000FFFFFFFFULL) lz -= 32; - if (value & 0x0000FFFF0000FFFFULL) lz -= 16; - if (value & 0x00FF00FF00FF00FFULL) lz -= 8; - if (value & 0x0F0F0F0F0F0F0F0FULL) lz -= 4; - if (value & 0x3333333333333333ULL) lz -= 2; - if (value & 0x5555555555555555ULL) lz -= 1; - - return lz; -} - /** * Given a number of nodes return the depth required to store them * in a fully balanced binary tree. @@ -56,12 +15,11 @@ constexpr int clz_power_2(uint64_t value) { * @param node_count - the number of nodes in the implied tree * @return the max depth of the minimal tree that stores them */ -constexpr int calcluate_max_depth(uint64_t node_count) { - if (node_count == 0) { +constexpr uint64_t calculate_max_depth(uint64_t node_count) { + if (node_count == 0) return 0; - } - auto implied_count = next_power_of_2(node_count); - return clz_power_2(implied_count) + 1; + // following is non-floating point equivalent to `std::ceil(std::log2(node_count)) + 1)` (and about 9x faster) + return std::bit_width(std::bit_ceil(node_count)); } template @@ -167,7 +125,7 @@ class incremental_merkle_impl { */ const DigestType& append(const DigestType& digest) { bool partial = false; - auto max_depth = detail::calcluate_max_depth(_node_count + 1); + auto max_depth = detail::calculate_max_depth(_node_count + 1); auto current_depth = max_depth - 1; auto index = _node_count; auto top = digest; @@ -246,6 +204,6 @@ class incremental_merkle_impl { typedef incremental_merkle_impl incremental_merkle; typedef incremental_merkle_impl shared_incremental_merkle; -} } /// eosio::chain +} /// eosio::chain FC_REFLECT( eosio::chain::incremental_merkle, (_active_nodes)(_node_count) ); diff --git a/libraries/chain/include/eosio/chain/permission_object.hpp b/libraries/chain/include/eosio/chain/permission_object.hpp index d323a1ef89..5547dd2860 100644 --- a/libraries/chain/include/eosio/chain/permission_object.hpp +++ b/libraries/chain/include/eosio/chain/permission_object.hpp @@ -23,7 +23,7 @@ namespace eosio { namespace chain { class permission_object : public chainbase::object { - OBJECT_CTOR(permission_object, (auth) ) + OBJECT_CTOR(permission_object, (auth)) id_type id; permission_usage_object::id_type usage_id; diff --git a/libraries/chain/include/eosio/chain/platform_timer_accuracy.hpp b/libraries/chain/include/eosio/chain/platform_timer_accuracy.hpp old mode 100755 new mode 100644 diff --git a/libraries/chain/include/eosio/chain/producer_schedule.hpp b/libraries/chain/include/eosio/chain/producer_schedule.hpp index 6a12e85791..af4f513bc8 100644 --- a/libraries/chain/include/eosio/chain/producer_schedule.hpp +++ b/libraries/chain/include/eosio/chain/producer_schedule.hpp @@ -46,15 +46,16 @@ namespace eosio { namespace chain { }; } + struct block_signing_authority_v0; + struct shared_block_signing_authority_v0 { - shared_block_signing_authority_v0() = delete; + shared_block_signing_authority_v0() = default; + shared_block_signing_authority_v0( const block_signing_authority_v0& ); shared_block_signing_authority_v0( const shared_block_signing_authority_v0& ) = default; shared_block_signing_authority_v0( shared_block_signing_authority_v0&& ) = default; shared_block_signing_authority_v0& operator= ( shared_block_signing_authority_v0 && ) = default; shared_block_signing_authority_v0& operator= ( const shared_block_signing_authority_v0 & ) = default; - - explicit shared_block_signing_authority_v0( chainbase::allocator alloc ) - :keys(alloc){} + shared_block_signing_authority_v0& operator= ( const block_signing_authority_v0 & ); uint32_t threshold = 0; shared_vector keys; @@ -62,8 +63,13 @@ namespace eosio { namespace chain { using shared_block_signing_authority = std::variant; + struct producer_authority; + struct shared_producer_authority { - shared_producer_authority() = delete; + shared_producer_authority() = default; + explicit shared_producer_authority(const producer_authority& ); + shared_producer_authority& operator=(const producer_authority& ); + shared_producer_authority( const shared_producer_authority& ) = default; shared_producer_authority( shared_producer_authority&& ) = default; shared_producer_authority& operator= ( shared_producer_authority && ) = default; @@ -78,11 +84,13 @@ namespace eosio { namespace chain { shared_block_signing_authority authority; }; + struct producer_authority_schedule; + struct shared_producer_authority_schedule { - shared_producer_authority_schedule() = delete; + shared_producer_authority_schedule() = default; - explicit shared_producer_authority_schedule( chainbase::allocator alloc ) - :producers(alloc){} + shared_producer_authority_schedule( const producer_authority_schedule& ); + shared_producer_authority_schedule& operator=(const producer_authority_schedule& ); shared_producer_authority_schedule( const shared_producer_authority_schedule& ) = default; shared_producer_authority_schedule( shared_producer_authority_schedule&& ) = default; @@ -127,18 +135,6 @@ namespace eosio { namespace chain { return {total_weight >= threshold, num_relevant_keys}; } - auto to_shared(chainbase::allocator alloc) const { - shared_block_signing_authority_v0 result(alloc); - result.threshold = threshold; - result.keys.clear(); - result.keys.reserve(keys.size()); - for (const auto& k: keys) { - result.keys.emplace_back(shared_key_weight::convert(alloc, k)); - } - - return result; - } - static auto from_shared(const shared_block_signing_authority_v0& src) { block_signing_authority_v0 result; result.threshold = src.threshold; @@ -186,14 +182,6 @@ namespace eosio { namespace chain { return keys_satisfy_and_relevant(presented_keys, authority); } - auto to_shared(chainbase::allocator alloc) const { - auto shared_auth = std::visit([&alloc](const auto& a) { - return a.to_shared(alloc); - }, authority); - - return shared_producer_authority(producer_name, std::move(shared_auth)); - } - static auto from_shared( const shared_producer_authority& src ) { producer_authority result; result.producer_name = src.producer_name; @@ -247,17 +235,6 @@ namespace eosio { namespace chain { ,producers(producers) {} - auto to_shared(chainbase::allocator alloc) const { - auto result = shared_producer_authority_schedule(alloc); - result.version = version; - result.producers.clear(); - result.producers.reserve( producers.size() ); - for( const auto& p : producers ) { - result.producers.emplace_back(p.to_shared(alloc)); - } - return result; - } - static auto from_shared( const shared_producer_authority_schedule& src ) { producer_authority_schedule result; result.version = src.version; diff --git a/libraries/chain/include/eosio/chain/protocol_state_object.hpp b/libraries/chain/include/eosio/chain/protocol_state_object.hpp index dc0eabd1f1..c2ffae1b76 100644 --- a/libraries/chain/include/eosio/chain/protocol_state_object.hpp +++ b/libraries/chain/include/eosio/chain/protocol_state_object.hpp @@ -16,9 +16,14 @@ namespace eosio { namespace chain { */ class protocol_state_object : public chainbase::object { - OBJECT_CTOR(protocol_state_object, (activated_protocol_features)(preactivated_protocol_features)(whitelisted_intrinsics)) - public: + template + protocol_state_object(Constructor&& c, chainbase::constructor_tag) : + id(0), + whitelisted_intrinsics(*activated_protocol_features.get_allocator(this)) { + c(*this); + } + struct activated_protocol_feature { digest_type feature_digest; uint32_t activation_block_num = 0; diff --git a/libraries/chain/include/eosio/chain/snapshot_scheduler.hpp b/libraries/chain/include/eosio/chain/snapshot_scheduler.hpp index fd9475d438..cc32489a66 100644 --- a/libraries/chain/include/eosio/chain/snapshot_scheduler.hpp +++ b/libraries/chain/include/eosio/chain/snapshot_scheduler.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include #include diff --git a/libraries/chain/include/eosio/chain/subjective_billing.hpp b/libraries/chain/include/eosio/chain/subjective_billing.hpp index d83ae3677b..cec47e8092 100644 --- a/libraries/chain/include/eosio/chain/subjective_billing.hpp +++ b/libraries/chain/include/eosio/chain/subjective_billing.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -81,9 +80,9 @@ class subjective_billing { } } - void remove_subjective_billing( const chain::block_state_ptr& bsp, uint32_t time_ordinal ) { + void remove_subjective_billing( const chain::signed_block_ptr& block, uint32_t time_ordinal ) { if( !_trx_cache_index.empty() ) { - for( const auto& receipt : bsp->block->transactions ) { + for( const auto& receipt : block->transactions ) { if( std::holds_alternative(receipt.trx) ) { const auto& pt = std::get(receipt.trx); remove_subjective_billing( pt.id(), time_ordinal ); @@ -151,11 +150,11 @@ class subjective_billing { } } - void on_block( fc::logger& log, const chain::block_state_ptr& bsp, const fc::time_point& now ) { - if( bsp == nullptr || _disabled ) return; + void on_block( fc::logger& log, const chain::signed_block_ptr& block, const fc::time_point& now ) { + if( block == nullptr || _disabled ) return; const auto time_ordinal = time_ordinal_for(now); const auto orig_count = _account_subjective_bill_cache.size(); - remove_subjective_billing( bsp, time_ordinal ); + remove_subjective_billing( block, time_ordinal ); if (orig_count > 0) { fc_dlog( log, "Subjective billed accounts ${n} removed ${r}", ("n", orig_count)("r", orig_count - _account_subjective_bill_cache.size()) ); diff --git a/libraries/chain/include/eosio/chain/transaction_metadata.hpp b/libraries/chain/include/eosio/chain/transaction_metadata.hpp index 5e585df6e7..7105f95b28 100644 --- a/libraries/chain/include/eosio/chain/transaction_metadata.hpp +++ b/libraries/chain/include/eosio/chain/transaction_metadata.hpp @@ -83,6 +83,12 @@ class transaction_metadata { start_recover_keys( packed_transaction_ptr trx, boost::asio::io_context& thread_pool, const chain_id_type& chain_id, fc::microseconds time_limit, trx_type t, uint32_t max_variable_sig_size = UINT32_MAX ); + /// Thread safe. + /// @returns transaction_metadata_ptr or throws + static transaction_metadata_ptr + recover_keys( packed_transaction_ptr trx, + const chain_id_type& chain_id, fc::microseconds time_limit, + trx_type t, uint32_t max_variable_sig_size = UINT32_MAX ); /// @returns constructed transaction_metadata with no key recovery (sig_cpu_usage=0, recovered_pub_keys=empty) static transaction_metadata_ptr diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index 99466395d7..102b9f0dd6 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -25,17 +25,15 @@ #include #define OBJECT_CTOR1(NAME) \ - NAME() = delete; \ public: \ - template \ - NAME(Constructor&& c, chainbase::allocator) \ + template \ + NAME(Constructor&& c, chainbase::constructor_tag) \ { c(*this); } -#define OBJECT_CTOR2_MACRO(x, y, field) ,field(a) +#define OBJECT_CTOR2_MACRO(x, y, field) ,field() #define OBJECT_CTOR2(NAME, FIELDS) \ - NAME() = delete; \ public: \ - template \ - NAME(Constructor&& c, chainbase::allocator a) \ + template \ + NAME(Constructor&& c, chainbase::constructor_tag) \ : id(0) BOOST_PP_SEQ_FOR_EACH(OBJECT_CTOR2_MACRO, _, FIELDS) \ { c(*this); } #define OBJECT_CTOR(...) BOOST_PP_OVERLOAD(OBJECT_CTOR, __VA_ARGS__)(__VA_ARGS__) @@ -86,10 +84,10 @@ namespace eosio::chain { using chainbase::allocator; using shared_string = chainbase::shared_string; + template - using shared_vector = boost::interprocess::vector>; - template - using shared_set = boost::interprocess::set, allocator>; + using shared_vector = chainbase::shared_vector; + template using shared_flat_multimap = boost::interprocess::flat_multimap< K, V, std::less, allocator< std::pair > >; @@ -99,25 +97,23 @@ namespace eosio::chain { * serialization and to/from variant */ class shared_blob : public shared_string { - public: - shared_blob() = delete; - shared_blob(shared_blob&&) = default; - - shared_blob(const shared_blob& s) = default; - + public: + shared_blob() = default; - shared_blob& operator=(const shared_blob& s) = default; + shared_blob(shared_blob&&) = default; + shared_blob(const shared_blob& s) = default; - shared_blob& operator=(shared_blob&& ) = default; + explicit shared_blob(std::string_view s) : shared_string(s) {} - template - shared_blob(InputIterator f, InputIterator l, const allocator_type& a) - :shared_string(f,l,a) - {} + template + shared_blob(InputIterator f, InputIterator l) : shared_string(f, l) {} - shared_blob(const allocator_type& a) - :shared_string(a) - {} + shared_blob& operator=(const shared_blob& s) = default; + shared_blob& operator=(shared_blob&& ) = default; + shared_blob& operator=(std::string_view sv) { + static_cast(*this) = sv; + return *this; + } }; using action_name = name; @@ -410,22 +406,4 @@ namespace eosio::chain { } // eosio::chain -namespace chainbase { - // chainbase::shared_cow_string - template inline DataStream& operator<<( DataStream& s, const chainbase::shared_cow_string& v ) { - FC_ASSERT( v.size() <= MAX_SIZE_OF_BYTE_ARRAYS ); - fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); - if( v.size() ) s.write( v.data(), v.size() ); - return s; - } - - template inline DataStream& operator>>( DataStream& s, chainbase::shared_cow_string& v ) { - fc::unsigned_int size; fc::raw::unpack( s, size ); - FC_ASSERT( size.value <= MAX_SIZE_OF_BYTE_ARRAYS ); - FC_ASSERT( v.size() == 0 ); - v.resize_and_fill(size.value, [&s](char* buf, std::size_t sz) { s.read(buf, sz); }); - return s; - } -} - FC_REFLECT_EMPTY( eosio::chain::void_t ) diff --git a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp index 946ad65a8e..4480c06abc 100644 --- a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp +++ b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -114,10 +114,10 @@ class unapplied_transaction_queue { return true; } - void clear_applied( const block_state_ptr& bs ) { + void clear_applied( const signed_block_ptr& block ) { if( empty() ) return; auto& idx = queue.get(); - for( const auto& receipt : bs->block->transactions ) { + for( const auto& receipt : block->transactions ) { if( std::holds_alternative(receipt.trx) ) { const auto& pt = std::get(receipt.trx); auto itr = idx.find( pt.id() ); @@ -136,7 +136,7 @@ class unapplied_transaction_queue { void add_forked( const branch_type& forked_branch ) { // forked_branch is in reverse order for( auto ritr = forked_branch.rbegin(), rend = forked_branch.rend(); ritr != rend; ++ritr ) { - const block_state_ptr& bsptr = *ritr; + const block_state_legacy_ptr& bsptr = *ritr; for( auto itr = bsptr->trxs_metas().begin(), end = bsptr->trxs_metas().end(); itr != end; ++itr ) { const auto& trx = *itr; auto insert_itr = queue.insert( { trx, trx_enum_type::forked } ); diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/config.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/config.hpp index c7278931e4..558d2b7305 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/config.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/config.hpp @@ -9,6 +9,10 @@ #include +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + namespace eosio { namespace chain { namespace eosvmoc { struct config { @@ -20,7 +24,11 @@ struct config { // libtester disables the limits in all tests, except enforces the limits // in the tests in unittests/eosvmoc_limits_tests.cpp. std::optional cpu_limit {20u}; +#if __has_feature(undefined_behavior_sanitizer) || __has_feature(address_sanitizer) + std::optional vm_limit; // UBSAN & ASAN can add massive virtual memory usage; don't enforce vm limits when either of them are enabled +#else std::optional vm_limit {512u*1024u*1024u}; +#endif std::optional stack_size_limit {16u*1024u}; std::optional generated_code_size_limit {16u*1024u*1024u}; }; diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.h b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.h index 28a8bd962e..03efd64d1e 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.h +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.h @@ -7,7 +7,9 @@ #ifdef __cplusplus #include #include -namespace eosio { namespace chain {class apply_context;}} +namespace eosio::chain { + class apply_context; +} #endif struct eos_vm_oc_control_block { @@ -38,3 +40,9 @@ struct eos_vm_oc_control_block { int64_t max_linear_memory_pages; void* globals; }; + +#ifdef __cplusplus +namespace eosio::chain::eosvmoc { + using control_block = eos_vm_oc_control_block; +} +#endif \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.hpp index 6c8d6f9fb9..95583457bd 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/eos-vm-oc.hpp @@ -12,13 +12,7 @@ #include #include -namespace eosio { namespace chain { - -class apply_context; - -namespace eosvmoc { - -using control_block = eos_vm_oc_control_block; +namespace eosio::chain::eosvmoc { struct no_offset{}; struct code_offset { @@ -52,7 +46,7 @@ enum eosvmoc_exitcode : int { static constexpr uint8_t current_codegen_version = 1; -}}} +} FC_REFLECT(eosio::chain::eosvmoc::no_offset, ); FC_REFLECT(eosio::chain::eosvmoc::code_offset, (offset)); diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/ipc_helpers.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/ipc_helpers.hpp index fcb5853731..8a5a001971 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/ipc_helpers.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/ipc_helpers.hpp @@ -1,14 +1,12 @@ #pragma once #include +#include #include #include -#include -#include - namespace eosio { namespace chain { namespace eosvmoc { class wrapped_fd { @@ -54,7 +52,7 @@ bool write_message_with_fds(int fd_to_send_to, const eosvmoc_message& message, c template wrapped_fd memfd_for_bytearray(const T& bytes) { - int fd = syscall(SYS_memfd_create, "eosvmoc_code", MFD_CLOEXEC); + int fd = exec_sealed_memfd_create("eosvmoc_code"); FC_ASSERT(fd >= 0, "Failed to create memfd"); FC_ASSERT(ftruncate(fd, bytes.size()) == 0, "failed to grow memfd"); if(bytes.size()) { diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memfd_helpers.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memfd_helpers.hpp new file mode 100644 index 0000000000..2f6bb14c80 --- /dev/null +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memfd_helpers.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace eosio::chain::eosvmoc { + +// added in glibc 2.38 +#ifndef MFD_NOEXEC_SEAL +#define MFD_NOEXEC_SEAL 8U +#endif + +inline int exec_sealed_memfd_create(const char* name) { + //kernels 6.3 through 6.6 by default warn when neither MFD_NOEXEC_SEAL nor MFD_EXEC are passed; optionally 6.3+ + // may enforce MFD_NOEXEC_SEAL. Prior to 6.3 these flags will EINVAL. + if(int ret = memfd_create(name, MFD_CLOEXEC | MFD_NOEXEC_SEAL); ret >= 0 || errno != EINVAL) + return ret; + return memfd_create(name, MFD_CLOEXEC); +} + +} diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memory.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memory.hpp index 2197878d30..6819b58d74 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memory.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/memory.hpp @@ -1,14 +1,15 @@ #pragma once +#include #include -#include +#include #include #include #include #include -namespace eosio { namespace chain { namespace eosvmoc { +namespace eosio::chain::eosvmoc { class memory { static constexpr uint64_t intrinsic_count = intrinsic_table_size(); @@ -66,7 +67,7 @@ class memory { uint8_t* fullpage_base; }; -}}} +} #define OFFSET_OF_CONTROL_BLOCK_MEMBER(M) (-(int)eosio::chain::eosvmoc::memory::cb_offset + (int)offsetof(eosio::chain::eosvmoc::control_block, M)) #define OFFSET_OF_FIRST_INTRINSIC ((int)-eosio::chain::eosvmoc::memory::first_intrinsic_offset) diff --git a/libraries/chain/producer_schedule.cpp b/libraries/chain/producer_schedule.cpp index b4c13338d5..97619b588f 100644 --- a/libraries/chain/producer_schedule.cpp +++ b/libraries/chain/producer_schedule.cpp @@ -1,6 +1,6 @@ #include -namespace eosio { namespace chain { +namespace eosio::chain { fc::variant producer_authority::get_abi_variant() const { auto authority_variant = std::visit([](const auto& a){ @@ -20,4 +20,40 @@ fc::variant producer_authority::get_abi_variant() const { ("authority", std::move(authority_variant)); } -} } /// eosio::chain +shared_producer_authority::shared_producer_authority(const producer_authority& pa) : + producer_name(pa.producer_name), + authority(std::visit([](const T& a) { return T(a);}, pa.authority)) +{ +} + +shared_producer_authority& shared_producer_authority::operator=(const producer_authority& pa) { + producer_name = pa.producer_name; + authority = std::visit([](const T& a) { return T(a);}, pa.authority); + return *this; +} + +shared_block_signing_authority_v0::shared_block_signing_authority_v0(const block_signing_authority_v0& bsa) : + threshold(bsa.threshold), + keys(bsa.keys) +{ +} + +shared_block_signing_authority_v0& shared_block_signing_authority_v0::operator= (const block_signing_authority_v0 & bsa) { + threshold = bsa.threshold; + keys = bsa.keys; + return *this; +} + +shared_producer_authority_schedule::shared_producer_authority_schedule(const producer_authority_schedule& pas) : + version(pas.version), + producers(pas.producers) +{ +} + +shared_producer_authority_schedule& shared_producer_authority_schedule::operator=(const producer_authority_schedule& pas) { + version = pas.version; + producers = pas.producers; + return *this; +} + +} /// eosio::chain diff --git a/libraries/chain/protocol_state_object.cpp b/libraries/chain/protocol_state_object.cpp index 142df3b131..028b99b2b2 100644 --- a/libraries/chain/protocol_state_object.cpp +++ b/libraries/chain/protocol_state_object.cpp @@ -32,17 +32,9 @@ namespace eosio { namespace chain { protocol_state_object& value, chainbase::database& db ) { - value.activated_protocol_features.clear(); - value.activated_protocol_features.reserve( row.activated_protocol_features.size() ); - for( const auto& v : row.activated_protocol_features ) { - value.activated_protocol_features.emplace_back( v ); - } - - value.preactivated_protocol_features.clear(); - value.preactivated_protocol_features.reserve( row.preactivated_protocol_features.size() ); - for( const auto& v : row.preactivated_protocol_features ) { - value.preactivated_protocol_features.emplace_back( v ); - } + value.activated_protocol_features = row.activated_protocol_features; + + value.preactivated_protocol_features = row.preactivated_protocol_features; reset_intrinsic_whitelist( value.whitelisted_intrinsics, row.whitelisted_intrinsics ); diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 262d7995a7..a535f0579e 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace eosio { namespace chain { @@ -708,11 +709,12 @@ namespace eosio { namespace chain { { uint32_t new_action_ordinal = trace->action_traces.size() + 1; - trace->action_traces.reserve( new_action_ordinal ); + trace->action_traces.reserve( std::bit_ceil(new_action_ordinal) ); // bit_ceil to avoid vector copy on every reserve call. const action& provided_action = get_action_trace( action_ordinal ).act; - // The reserve above is required so that the emplace_back below does not invalidate the provided_action reference. + // The reserve above is required so that the emplace_back below does not invalidate the provided_action reference, + // which references an action within the `trace->action_traces` vector we are appending to. trace->action_traces.emplace_back( *trace, provided_action, receiver, context_free, new_action_ordinal, creator_action_ordinal, diff --git a/libraries/chain/transaction_metadata.cpp b/libraries/chain/transaction_metadata.cpp index f33e33192b..d49819dd16 100644 --- a/libraries/chain/transaction_metadata.cpp +++ b/libraries/chain/transaction_metadata.cpp @@ -12,15 +12,23 @@ recover_keys_future transaction_metadata::start_recover_keys( packed_transaction uint32_t max_variable_sig_size ) { return post_async_task( thread_pool, [trx{std::move(trx)}, chain_id, time_limit, t, max_variable_sig_size]() mutable { - fc::time_point deadline = time_limit == fc::microseconds::maximum() ? - fc::time_point::maximum() : fc::time_point::now() + time_limit; - check_variable_sig_size( trx, max_variable_sig_size ); - const signed_transaction& trn = trx->get_signed_transaction(); - flat_set recovered_pub_keys; - fc::microseconds cpu_usage = trn.get_signature_keys( chain_id, deadline, recovered_pub_keys ); - return std::make_shared( private_type(), std::move( trx ), cpu_usage, std::move( recovered_pub_keys ), t ); - } - ); + return recover_keys( std::move(trx), chain_id, time_limit, t, max_variable_sig_size ); + }); +} + +transaction_metadata_ptr transaction_metadata::recover_keys( packed_transaction_ptr trx, + const chain_id_type& chain_id, + fc::microseconds time_limit, + trx_type t, + uint32_t max_variable_sig_size ) +{ + fc::time_point deadline = time_limit == fc::microseconds::maximum() ? + fc::time_point::maximum() : fc::time_point::now() + time_limit; + check_variable_sig_size( trx, max_variable_sig_size ); + const signed_transaction& trn = trx->get_signed_transaction(); + flat_set recovered_pub_keys; + fc::microseconds cpu_usage = trn.get_signature_keys( chain_id, deadline, recovered_pub_keys ); + return std::make_shared( private_type(), std::move( trx ), cpu_usage, std::move( recovered_pub_keys ), t ); } size_t transaction_metadata::get_estimated_size() const { diff --git a/libraries/chain/webassembly/runtimes/eos-vm-oc/compile_trampoline.cpp b/libraries/chain/webassembly/runtimes/eos-vm-oc/compile_trampoline.cpp index 11467afd27..0bd7f2cc9a 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm-oc/compile_trampoline.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm-oc/compile_trampoline.cpp @@ -122,7 +122,8 @@ void run_compile(wrapped_fd&& response_sock, wrapped_fd&& wasm_code, uint64_t st if(base_offset + data_segment.data.size() > initial_mem.size()) initial_mem.resize(base_offset + data_segment.data.size(), 0x00); - memcpy(initial_mem.data() + base_offset, data_segment.data.data(), data_segment.data.size()); + if(data_segment.data.size()) + memcpy(initial_mem.data() + base_offset, data_segment.data.data(), data_segment.data.size()); } result_message.initdata_prologue_size = prologue.end() - prologue_it; diff --git a/libraries/chain/webassembly/runtimes/eos-vm-oc/memory.cpp b/libraries/chain/webassembly/runtimes/eos-vm-oc/memory.cpp index dd46a761af..38c0f3e1e7 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm-oc/memory.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm-oc/memory.cpp @@ -1,20 +1,19 @@ #include #include #include +#include #include #include -#include #include -#include namespace eosio { namespace chain { namespace eosvmoc { memory::memory(uint64_t sliced_pages) { uint64_t number_slices = sliced_pages + 1; uint64_t wasm_memory_size = sliced_pages * wasm_constraints::wasm_page_size; - int fd = syscall(SYS_memfd_create, "eosvmoc_mem", MFD_CLOEXEC); + int fd = exec_sealed_memfd_create("eosvmoc_mem"); FC_ASSERT(fd >= 0, "Failed to create memory memfd"); auto cleanup_fd = fc::make_scoped_exit([&fd](){close(fd);}); int ret = ftruncate(fd, wasm_memory_size+memory_prologue_size); @@ -41,7 +40,7 @@ memory::memory(uint64_t sliced_pages) { uintptr_t* const intrinsic_jump_table = reinterpret_cast(zeropage_base - first_intrinsic_offset); const intrinsic_map_t& intrinsics = get_intrinsic_map(); for(const auto& intrinsic : intrinsics) - intrinsic_jump_table[-intrinsic.second.ordinal] = (uintptr_t)intrinsic.second.function_ptr; + intrinsic_jump_table[-(int)intrinsic.second.ordinal] = (uintptr_t)intrinsic.second.function_ptr; } memory::~memory() { diff --git a/libraries/chain/whitelisted_intrinsics.cpp b/libraries/chain/whitelisted_intrinsics.cpp index 021e93b19d..835f6f4d03 100644 --- a/libraries/chain/whitelisted_intrinsics.cpp +++ b/libraries/chain/whitelisted_intrinsics.cpp @@ -59,8 +59,7 @@ namespace eosio { namespace chain { whitelisted_intrinsics.emplace( std::piecewise_construct, std::forward_as_tuple( h ), - std::forward_as_tuple( name.data(), name.size(), - whitelisted_intrinsics.get_allocator() ) + std::forward_as_tuple( name.data(), name.size() ) ); } @@ -85,8 +84,7 @@ namespace eosio { namespace chain { uint64_t h = static_cast( std::hash{}( name ) ); whitelisted_intrinsics.emplace( std::piecewise_construct, std::forward_as_tuple( h ), - std::forward_as_tuple( name.data(), name.size(), - whitelisted_intrinsics.get_allocator() ) + std::forward_as_tuple( name.data(), name.size() ) ); } } diff --git a/libraries/chainbase b/libraries/chainbase index c907126b15..0324e06d0b 160000 --- a/libraries/chainbase +++ b/libraries/chainbase @@ -1 +1 @@ -Subproject commit c907126b1555a6d41eb29d7a7cf92e3070e21f47 +Subproject commit 0324e06d0b8f4e7e09b0d41c7f6a086fd1a7bac7 diff --git a/libraries/eos-vm b/libraries/eos-vm index 33e91ebf90..aa8bd0a310 160000 --- a/libraries/eos-vm +++ b/libraries/eos-vm @@ -1 +1 @@ -Subproject commit 33e91ebf90088152477b7e7795cf5c871e70cb5c +Subproject commit aa8bd0a310bd39aa225dcb6c73ee069f697a0ccd diff --git a/libraries/libfc/include/fc/io/raw.hpp b/libraries/libfc/include/fc/io/raw.hpp index dd570fe1fa..cc4317f797 100644 --- a/libraries/libfc/include/fc/io/raw.hpp +++ b/libraries/libfc/include/fc/io/raw.hpp @@ -17,17 +17,11 @@ #include #include -#include -#include -#include #include namespace fc { namespace raw { - namespace bip = boost::interprocess; - using shared_string = bip::basic_string< char, std::char_traits< char >, bip::allocator >; - template using UInt = boost::multiprecision::number< boost::multiprecision::cpp_int_backend >; @@ -42,10 +36,15 @@ namespace fc { template void unpack( Stream& s, boost::multiprecision::number& n ); template - inline void pack( Stream& s, const Arg0& a0, Args... args ) { + inline void pack( Stream& s, const Arg0& a0, const Args&... args ) { pack( s, a0 ); pack( s, args... ); } + template + inline void unpack( Stream& s, Arg0& a0, Args&... args ) { + unpack( s, a0 ); + unpack( s, args... ); + } template inline void pack( Stream& s, const fc::exception& e ) @@ -249,7 +248,12 @@ namespace fc { FC_ASSERT( vi == tmp ); } - template inline void pack( Stream& s, const char* v ) { fc::raw::pack( s, std::string(v) ); } + template inline void pack( Stream& s, const char* v ) { + size_t sz = std::strlen(v); + FC_ASSERT( sz <= MAX_SIZE_OF_BYTE_ARRAYS ); + fc::raw::pack( s, unsigned_int(sz)); + if( sz ) s.write( v, sz ); + } template void pack( Stream& s, const safe& v ) { fc::raw::pack( s, v.value ); } @@ -309,22 +313,6 @@ namespace fc { v = std::string(tmp.data(),tmp.data()+tmp.size()); else v = std::string(); } - - // bip::basic_string - template inline void pack( Stream& s, const shared_string& v ) { - FC_ASSERT( v.size() <= MAX_SIZE_OF_BYTE_ARRAYS ); - fc::raw::pack( s, unsigned_int((uint32_t)v.size())); - if( v.size() ) s.write( v.c_str(), v.size() ); - } - - template inline void unpack( Stream& s, shared_string& v ) { - std::vector tmp; fc::raw::unpack(s,tmp); - FC_ASSERT(v.size() == 0); - if( tmp.size() ) { - v.append(tmp.begin(), tmp.end()); - } - } - // bool template inline void pack( Stream& s, const bool& v ) { fc::raw::pack( s, uint8_t(v) ); } template inline void unpack( Stream& s, bool& v ) @@ -464,6 +452,16 @@ namespace fc { } } + template + inline void pack( Stream& s, const std::tuple& tup ) { + auto l = [&s](const auto&... v) { fc::raw::pack( s, v... ); }; + std::apply(l, tup); + } + template + inline void unpack( Stream& s, std::tuple& tup ) { + auto l = [&s](auto&... v) { fc::raw::unpack( s, v... ); }; + std::apply(l, tup); + } template inline void pack( Stream& s, const std::pair& value ) { diff --git a/libraries/libfc/libraries/bn256 b/libraries/libfc/libraries/bn256 index eae77bf03d..b5adbb76d4 160000 --- a/libraries/libfc/libraries/bn256 +++ b/libraries/libfc/libraries/bn256 @@ -1 +1 @@ -Subproject commit eae77bf03dcf02579e967b0749ed5c175bd06c5a +Subproject commit b5adbb76d456e85385296a1388ba18f6f07d9d9e diff --git a/libraries/libfc/secp256k1/secp256k1 b/libraries/libfc/secp256k1/secp256k1 index 199d27cea3..1ad5185cd4 160000 --- a/libraries/libfc/secp256k1/secp256k1 +++ b/libraries/libfc/secp256k1/secp256k1 @@ -1 +1 @@ -Subproject commit 199d27cea32203b224b208627533c2e813cd3b21 +Subproject commit 1ad5185cd42c0636104129fcc9f6a4bf9c67cc40 diff --git a/libraries/libfc/test/crypto/test_webauthn.cpp b/libraries/libfc/test/crypto/test_webauthn.cpp index 600d543f5c..5a7f429c28 100644 --- a/libraries/libfc/test/crypto/test_webauthn.cpp +++ b/libraries/libfc/test/crypto/test_webauthn.cpp @@ -38,7 +38,7 @@ static fc::crypto::webauthn::signature make_webauthn_sig(const fc::crypto::r1::p //used for many below static const r1::private_key priv = fc::crypto::r1::private_key::generate(); static const r1::public_key pub = priv.get_public_key(); -static const fc::sha256 d = fc::sha256::hash("sup"s); +static const fc::sha256 d = fc::sha256::hash("monkeys"s); static const fc::sha256 origin_hash = fc::sha256::hash("fctesting.invalid"s); BOOST_AUTO_TEST_SUITE(webauthn_suite) @@ -166,6 +166,82 @@ BOOST_AUTO_TEST_CASE(challenge_non_base64) try { }); } FC_LOG_AND_RETHROW(); +//valid signature but replace url-safe base64 characters with the non-url safe characters +BOOST_AUTO_TEST_CASE(challenge_wrong_base64_chars) try { + webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE, "fctesting.invalid"); + std::string b64 = fc::base64url_encode(d.data(), d.data_size()); + + BOOST_REQUIRE(b64[1] == '_'); + BOOST_REQUIRE(b64[18] == '_'); + BOOST_REQUIRE(b64[36] == '-'); + + b64[1] = b64[18] = '/'; + b64[36] = '+'; + + std::string json = "{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" + b64 + "\"}"; + + std::vector auth_data(37); + memcpy(auth_data.data(), origin_hash.data(), sizeof(origin_hash)); + + BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data, json).recover(d, true), fc::exception, [](const fc::exception& e) { + return e.to_detail_string().find("encountered non-base64 character") != std::string::npos; + }); +} FC_LOG_AND_RETHROW(); + +//valid signature but replace the padding '=' with '.' +BOOST_AUTO_TEST_CASE(challenge_base64_dot_padding) try { + webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE, "fctesting.invalid"); + std::string b64 = fc::base64url_encode(d.data(), d.data_size()); + char& end = b64.back(); + + BOOST_REQUIRE(end == '='); + end = '.'; + + std::string json = "{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" + b64 + "\"}"; + + std::vector auth_data(37); + memcpy(auth_data.data(), origin_hash.data(), sizeof(origin_hash)); + + BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data, json).recover(d, true), fc::exception, [](const fc::exception& e) { + return e.to_detail_string().find("encountered non-base64 character") != std::string::npos; + }); +} FC_LOG_AND_RETHROW(); + +//valid signature but remove padding +BOOST_AUTO_TEST_CASE(challenge_no_padding) try { + webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE, "fctesting.invalid"); + std::string b64 = fc::base64url_encode(d.data(), d.data_size()); + + BOOST_REQUIRE(b64.back() == '='); + b64.resize(b64.size() - 1); + + std::string json = "{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" + b64 + "\"}"; + + std::vector auth_data(37); + memcpy(auth_data.data(), origin_hash.data(), sizeof(origin_hash)); + + BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data, json).recover(d, true)); +} FC_LOG_AND_RETHROW(); + +//valid signature but tack extra bytes in the challenge +BOOST_AUTO_TEST_CASE(challenge_extra_bytes) try { + webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE, "fctesting.invalid"); + std::string b64 = fc::base64url_encode(d.data(), d.data_size()); + + BOOST_REQUIRE(b64.back() == '='); + b64.resize(b64.size() - 1); + b64.append("abcd"); + + std::string json = "{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" + b64 + "\"}"; + + std::vector auth_data(37); + memcpy(auth_data.data(), origin_hash.data(), sizeof(origin_hash)); + + BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data, json).recover(d, true), fc::exception, [](const fc::exception& e) { + return e.to_detail_string().find("size mismatch") != std::string::npos; + }); +} FC_LOG_AND_RETHROW(); + //valid signature but with some other digest in the challenge that is not the one we are recovering from BOOST_AUTO_TEST_CASE(challenge_wrong) try { webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE, "fctesting.invalid"); diff --git a/libraries/libfc/test/network/test_message_buffer.cpp b/libraries/libfc/test/network/test_message_buffer.cpp index 5e603b32bd..8a6ab2adb6 100644 --- a/libraries/libfc/test/network/test_message_buffer.cpp +++ b/libraries/libfc/test/network/test_message_buffer.cpp @@ -344,6 +344,57 @@ BOOST_AUTO_TEST_CASE(message_buffer_datastream) { } } +BOOST_AUTO_TEST_CASE(message_buffer_datastream_tuple) { + using my_message_buffer_t = fc::message_buffer<1024>; + my_message_buffer_t mbuff; + + char buf[1024]; + fc::datastream ds( buf, 1024 ); + + using my_tuple = std::tuple; + my_tuple t(13, 42, "hello"); + fc::raw::pack( ds, t ); + + memcpy(mbuff.write_ptr(), buf, 1024); + mbuff.advance_write_ptr(1024); + + for( int i = 0; i < 3; ++i ) { + auto ds2 = mbuff.create_peek_datastream(); + my_tuple t2; + fc::raw::unpack( ds2, t2 ); + BOOST_CHECK( t == t2 ); + } + + { + auto ds2 = mbuff.create_datastream(); + my_tuple t2; + fc::raw::unpack( ds2, t2 ); + BOOST_CHECK( t == t2 ); + } +} + +BOOST_AUTO_TEST_CASE(message_buffer_datastream_variadic_pack_unpack) { + using my_message_buffer_t = fc::message_buffer<1024>; + my_message_buffer_t mbuff; + + char buf[1024]; + fc::datastream ds( buf, 1024 ); + + using my_tuple = std::tuple; + my_tuple t(13, 42, "hello"); + fc::raw::pack( ds, std::get<0>(t), std::get<1>(t), std::get<2>(t) ); + + memcpy(mbuff.write_ptr(), buf, 1024); + mbuff.advance_write_ptr(1024); + + for( int i = 0; i < 3; ++i ) { + auto ds2 = mbuff.create_peek_datastream(); + my_tuple t2; + fc::raw::unpack( ds2, std::get<0>(t2), std::get<1>(t2), std::get<2>(t2) ); + BOOST_CHECK( t == t2 ); + } +} + // Make sure that the memory allocation is thread-safe. // A previous version used boost::object_pool without synchronization. BOOST_AUTO_TEST_CASE(test_message_buffer) { diff --git a/libraries/libfc/test/test_base64.cpp b/libraries/libfc/test/test_base64.cpp index 526d7c75d0..d6a59e628b 100644 --- a/libraries/libfc/test/test_base64.cpp +++ b/libraries/libfc/test/test_base64.cpp @@ -27,8 +27,7 @@ BOOST_AUTO_TEST_CASE(base64dec) try { auto expected_output = "abc123$&()'?\xb4\xf5\x01\xfa~a"s; std::vector b64 = base64_decode(input); - std::string b64_str(b64.begin(), b64.end()); - BOOST_CHECK_EQUAL(expected_output, b64_str); + BOOST_CHECK_EQUAL(expected_output, std::string_view(b64.begin(), b64.end())); } FC_LOG_AND_RETHROW(); BOOST_AUTO_TEST_CASE(base64urldec) try { @@ -36,8 +35,7 @@ BOOST_AUTO_TEST_CASE(base64urldec) try { auto expected_output = "abc123$&()'?\xb4\xf5\x01\xfa~a"s; std::vector b64 = base64url_decode(input); - std::string b64_str(b64.begin(), b64.end()); - BOOST_CHECK_EQUAL(expected_output, b64_str); + BOOST_CHECK_EQUAL(expected_output, std::string_view(b64.begin(), b64.end())); } FC_LOG_AND_RETHROW(); BOOST_AUTO_TEST_CASE(base64dec_extraequals) try { @@ -45,8 +43,7 @@ BOOST_AUTO_TEST_CASE(base64dec_extraequals) try { auto expected_output = "abc123$&()'?\xb4\xf5\x01\xfa~a"s; std::vector b64 = base64_decode(input); - std::string b64_str(b64.begin(), b64.end()); - BOOST_CHECK_EQUAL(expected_output, b64_str); + BOOST_CHECK_EQUAL(expected_output, std::string_view(b64.begin(), b64.end())); } FC_LOG_AND_RETHROW(); BOOST_AUTO_TEST_CASE(base64dec_bad_stuff) try { diff --git a/libraries/state_history/include/eosio/state_history/trace_converter.hpp b/libraries/state_history/include/eosio/state_history/trace_converter.hpp index b25aefedf9..4cc6bef7cd 100644 --- a/libraries/state_history/include/eosio/state_history/trace_converter.hpp +++ b/libraries/state_history/include/eosio/state_history/trace_converter.hpp @@ -1,13 +1,11 @@ #pragma once -#include #include #include namespace eosio { namespace state_history { -using chain::block_state_ptr; using chain::transaction_id_type; struct trace_converter { @@ -15,7 +13,7 @@ struct trace_converter { std::optional onblock_trace; void add_transaction(const transaction_trace_ptr& trace, const chain::packed_transaction_ptr& transaction); - void pack(boost::iostreams::filtering_ostreambuf& ds, bool trace_debug_mode, const block_state_ptr& block_state); + void pack(boost::iostreams::filtering_ostreambuf& ds, bool trace_debug_mode, const chain::signed_block_ptr& block); }; } // namespace state_history diff --git a/libraries/state_history/trace_converter.cpp b/libraries/state_history/trace_converter.cpp index 48a8733895..3c137f5ecf 100644 --- a/libraries/state_history/trace_converter.cpp +++ b/libraries/state_history/trace_converter.cpp @@ -15,11 +15,11 @@ void trace_converter::add_transaction(const transaction_trace_ptr& trace, const } } -void trace_converter::pack(boost::iostreams::filtering_ostreambuf& obuf, bool trace_debug_mode, const block_state_ptr& block_state) { +void trace_converter::pack(boost::iostreams::filtering_ostreambuf& obuf, bool trace_debug_mode, const chain::signed_block_ptr& block) { std::vector traces; if (onblock_trace) traces.push_back(*onblock_trace); - for (auto& r : block_state->block->transactions) { + for (auto& r : block->transactions) { transaction_id_type id; if (std::holds_alternative(r.trx)) id = std::get(r.trx); diff --git a/libraries/testing/contracts/eosio.bios/eosio.bios.wasm b/libraries/testing/contracts/eosio.bios/eosio.bios.wasm old mode 100755 new mode 100644 diff --git a/libraries/testing/contracts/old_versions/v1.6.0-rc3/eosio.bios/eosio.bios.wasm b/libraries/testing/contracts/old_versions/v1.6.0-rc3/eosio.bios/eosio.bios.wasm old mode 100755 new mode 100644 diff --git a/libraries/testing/contracts/old_versions/v1.7.0-develop-preactivate_feature/eosio.bios/eosio.bios.wasm b/libraries/testing/contracts/old_versions/v1.7.0-develop-preactivate_feature/eosio.bios/eosio.bios.wasm old mode 100755 new mode 100644 diff --git a/libraries/testing/tester.cpp b/libraries/testing/tester.cpp index 8a9b7a0ad6..51672db7ad 100644 --- a/libraries/testing/tester.cpp +++ b/libraries/testing/tester.cpp @@ -321,9 +321,10 @@ namespace eosio { namespace testing { control->add_indices(); if (lambda) lambda(); chain_transactions.clear(); - control->accepted_block.connect([this]( const block_state_ptr& block_state ){ - FC_ASSERT( block_state->block ); - for( auto receipt : block_state->block->transactions ) { + control->accepted_block.connect([this]( block_signal_params t ){ + const auto& [ block, id ] = t; + FC_ASSERT( block ); + for( auto receipt : block->transactions ) { if( std::holds_alternative(receipt.trx) ) { auto &pt = std::get(receipt.trx); chain_transactions[pt.get_transaction().id()] = std::move(receipt); diff --git a/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp b/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp index 845314a558..4fe1c247d4 100644 --- a/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp +++ b/plugins/chain_interface/include/eosio/chain/plugin_interface.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -14,12 +14,10 @@ namespace eosio::chain::plugin_interface { struct chain_plugin_interface; namespace channels { - using pre_accepted_block = channel_decl; using rejected_block = channel_decl; - using accepted_block_header = channel_decl; - using accepted_block = channel_decl; - using irreversible_block = channel_decl; - using accepted_transaction = channel_decl; + using accepted_block_header = channel_decl; + using accepted_block = channel_decl; + using irreversible_block = channel_decl; using applied_transaction = channel_decl; } @@ -34,8 +32,8 @@ namespace eosio::chain::plugin_interface { namespace incoming { namespace methods { - // synchronously push a block/trx to a single provider, block_state_ptr may be null - using block_sync = method_decl&, const block_state_ptr&), first_provider_policy>; + // synchronously push a block/trx to a single provider, block_state_legacy_ptr may be null + using block_sync = method_decl&, const block_state_legacy_ptr&), first_provider_policy>; using transaction_async = method_decl), first_provider_policy>; } } diff --git a/plugins/chain_plugin/account_query_db.cpp b/plugins/chain_plugin/account_query_db.cpp index 19c6d2c1ac..f5a6cf6a32 100644 --- a/plugins/chain_plugin/account_query_db.cpp +++ b/plugins/chain_plugin/account_query_db.cpp @@ -194,9 +194,9 @@ namespace eosio::chain_apis { key_bimap.right.erase(key_range.first, key_range.second); } - bool is_rollback_required( const chain::block_state_ptr& bsp ) const { + bool is_rollback_required( const chain::signed_block_ptr& block ) const { std::shared_lock read_lock(rw_mutex); - const auto bnum = bsp->block->block_num(); + const auto bnum = block->block_num(); const auto& index = permission_info_index.get(); if (index.empty()) { @@ -231,10 +231,10 @@ namespace eosio::chain_apis { * * For each removed entry, this will create a new entry if there exists an equivalent {owner, name} permission * at the HEAD state of the chain. - * @param bsp - the block to rollback before + * @param block - the block to rollback before */ - void rollback_to_before( const chain::block_state_ptr& bsp ) { - const auto bnum = bsp->block->block_num(); + void rollback_to_before( const chain::signed_block_ptr& block ) { + const auto bnum = block->block_num(); auto& index = permission_info_index.get(); const auto& permission_by_owner = controller.db().get_index().indices().get(); @@ -265,8 +265,8 @@ namespace eosio::chain_apis { } else { const auto& po = *itr; - uint32_t last_updated_height = chain::block_timestamp_type(po.last_updated) == bsp->header.timestamp ? - bsp->block_num : last_updated_time_to_height(po.last_updated); + uint32_t last_updated_height = chain::block_timestamp_type(po.last_updated) == block->timestamp ? + bnum : last_updated_time_to_height(po.last_updated); index.modify(index.iterator_to(pi), [&po, last_updated_height](auto& mutable_pi) { mutable_pi.last_updated_height = last_updated_height; @@ -303,9 +303,9 @@ namespace eosio::chain_apis { /** * Pre-Commit step with const qualifier to guarantee it does not mutate * the thread-safe data set - * @param bsp + * @param block */ - auto commit_block_prelock( const chain::block_state_ptr& bsp ) const { + auto commit_block_prelock( const chain::signed_block_ptr& block ) const { permission_set_t updated; permission_set_t deleted; @@ -338,7 +338,7 @@ namespace eosio::chain_apis { if( onblock_trace ) process_trace(*onblock_trace); - for( const auto& r : bsp->block->transactions ) { + for( const auto& r : block->transactions ) { chain::transaction_id_type id; if( std::holds_alternative(r.trx)) { id = std::get(r.trx); @@ -352,31 +352,32 @@ namespace eosio::chain_apis { } } - return std::make_tuple(std::move(updated), std::move(deleted), is_rollback_required(bsp)); + return std::make_tuple(std::move(updated), std::move(deleted), is_rollback_required(block)); } /** * Commit a block of transactions to the account query DB * transaction traces need to be in the cache prior to this call - * @param bsp + * @param block */ - void commit_block(const chain::block_state_ptr& bsp ) { + void commit_block(const chain::signed_block_ptr& block) { permission_set_t updated; permission_set_t deleted; bool rollback_required = false; - std::tie(updated, deleted, rollback_required) = commit_block_prelock(bsp); + std::tie(updated, deleted, rollback_required) = commit_block_prelock(block); // optimistic skip of locking section if there is nothing to do if (!updated.empty() || !deleted.empty() || rollback_required) { std::unique_lock write_lock(rw_mutex); + auto block_num = block->block_num(); - rollback_to_before(bsp); + rollback_to_before(block); // insert this blocks time into the time map - time_to_block_num.emplace(bsp->header.timestamp, bsp->block_num); + time_to_block_num.emplace(block->timestamp, block_num); - const auto bnum = bsp->block_num; + const auto bnum = block_num; auto& index = permission_info_index.get(); const auto& permission_by_owner = controller.db().get_index().indices().get(); @@ -520,7 +521,7 @@ namespace eosio::chain_apis { } FC_LOG_AND_DROP(("ACCOUNT DB cache_transaction_trace ERROR")); } - void account_query_db::commit_block(const chain::block_state_ptr& block ) { + void account_query_db::commit_block( const chain::signed_block_ptr& block ) { try { _impl->commit_block(block); } FC_LOG_AND_DROP(("ACCOUNT DB commit_block ERROR")); diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index e395013697..f353b66803 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -16,11 +16,10 @@ #include #include #include +#include #include -#include - #include #include #include @@ -29,13 +28,6 @@ #include #include -// reflect chainbase::environment for --print-build-info option -FC_REFLECT_ENUM( chainbase::environment::os_t, - (OS_LINUX)(OS_MACOS)(OS_WINDOWS)(OS_OTHER) ) -FC_REFLECT_ENUM( chainbase::environment::arch_t, - (ARCH_X86_64)(ARCH_ARM)(ARCH_RISCV)(ARCH_OTHER) ) -FC_REFLECT(chainbase::environment, (debug)(os)(arch)(boost_version)(compiler) ) - const std::string deep_mind_logger_name("deep-mind"); eosio::chain::deep_mind_handler _deep_mind_log; @@ -154,11 +146,9 @@ using boost::signals2::scoped_connection; class chain_plugin_impl { public: chain_plugin_impl() - :pre_accepted_block_channel(app().get_channel()) - ,accepted_block_header_channel(app().get_channel()) + :accepted_block_header_channel(app().get_channel()) ,accepted_block_channel(app().get_channel()) ,irreversible_block_channel(app().get_channel()) - ,accepted_transaction_channel(app().get_channel()) ,applied_transaction_channel(app().get_channel()) ,incoming_block_sync_method(app().get_method()) ,incoming_transaction_async_method(app().get_method()) @@ -181,11 +171,9 @@ class chain_plugin_impl { // retained references to channels for easy publication - channels::pre_accepted_block::channel_type& pre_accepted_block_channel; channels::accepted_block_header::channel_type& accepted_block_header_channel; channels::accepted_block::channel_type& accepted_block_channel; channels::irreversible_block::channel_type& irreversible_block_channel; - channels::accepted_transaction::channel_type& accepted_transaction_channel; channels::applied_transaction::channel_type& applied_transaction_channel; // retained references to methods for easy calling @@ -199,11 +187,9 @@ class chain_plugin_impl { methods::get_last_irreversible_block_number::method_type::handle get_last_irreversible_block_number_provider; // scoped connections for chain controller - std::optional pre_accepted_block_connection; std::optional accepted_block_header_connection; std::optional accepted_block_connection; std::optional irreversible_block_connection; - std::optional accepted_transaction_connection; std::optional applied_transaction_connection; std::optional block_start_connection; @@ -1019,72 +1005,58 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) { } ); // relay signals to channels - pre_accepted_block_connection = chain->pre_accepted_block.connect([this](const signed_block_ptr& blk) { - auto itr = loaded_checkpoints.find( blk->block_num() ); - if( itr != loaded_checkpoints.end() ) { - auto id = blk->calculate_id(); - EOS_ASSERT( itr->second == id, checkpoint_exception, - "Checkpoint does not match for block number ${num}: expected: ${expected} actual: ${actual}", - ("num", blk->block_num())("expected", itr->second)("actual", id) - ); - } - - pre_accepted_block_channel.publish(priority::medium, blk); - }); - accepted_block_header_connection = chain->accepted_block_header.connect( - [this]( const block_state_ptr& blk ) { - accepted_block_header_channel.publish( priority::medium, blk ); + [this]( const block_signal_params& t ) { + accepted_block_header_channel.publish( priority::medium, t ); } ); - accepted_block_connection = chain->accepted_block.connect( [this]( const block_state_ptr& blk ) { + accepted_block_connection = chain->accepted_block.connect( [this]( const block_signal_params& t ) { + const auto& [ block, id ] = t; if (_account_query_db) { - _account_query_db->commit_block(blk); + _account_query_db->commit_block(block); } if (_trx_retry_db) { - _trx_retry_db->on_accepted_block(blk); + _trx_retry_db->on_accepted_block(block->block_num()); } if (_trx_finality_status_processing) { - _trx_finality_status_processing->signal_accepted_block(blk); + _trx_finality_status_processing->signal_accepted_block(block, id); } - accepted_block_channel.publish( priority::high, blk ); + accepted_block_channel.publish( priority::high, t ); } ); - irreversible_block_connection = chain->irreversible_block.connect( [this]( const block_state_ptr& blk ) { + irreversible_block_connection = chain->irreversible_block.connect( [this]( const block_signal_params& t ) { + const auto& [ block, id ] = t; + if (_trx_retry_db) { - _trx_retry_db->on_irreversible_block(blk); + _trx_retry_db->on_irreversible_block(block); } if (_trx_finality_status_processing) { - _trx_finality_status_processing->signal_irreversible_block(blk); + _trx_finality_status_processing->signal_irreversible_block(block, id); } - irreversible_block_channel.publish( priority::low, blk ); + irreversible_block_channel.publish( priority::low, t ); } ); - - accepted_transaction_connection = chain->accepted_transaction.connect( - [this]( const transaction_metadata_ptr& meta ) { - accepted_transaction_channel.publish( priority::low, meta ); - } ); - + applied_transaction_connection = chain->applied_transaction.connect( [this]( std::tuple t ) { + const auto& [ trace, ptrx ] = t; if (_account_query_db) { - _account_query_db->cache_transaction_trace(std::get<0>(t)); + _account_query_db->cache_transaction_trace(trace); } if (_trx_retry_db) { - _trx_retry_db->on_applied_transaction(std::get<0>(t), std::get<1>(t)); + _trx_retry_db->on_applied_transaction(trace, ptrx); } if (_trx_finality_status_processing) { - _trx_finality_status_processing->signal_applied_transaction(std::get<0>(t), std::get<1>(t)); + _trx_finality_status_processing->signal_applied_transaction(trace, ptrx); } - applied_transaction_channel.publish( priority::low, std::get<0>(t) ); + applied_transaction_channel.publish( priority::low, trace ); } ); if (_trx_finality_status_processing || _trx_retry_db) { @@ -1162,11 +1134,9 @@ void chain_plugin::plugin_startup() { } void chain_plugin_impl::plugin_shutdown() { - pre_accepted_block_connection.reset(); accepted_block_header_connection.reset(); accepted_block_connection.reset(); irreversible_block_connection.reset(); - accepted_transaction_connection.reset(); applied_transaction_connection.reset(); block_start_connection.reset(); chain.reset(); @@ -1207,7 +1177,7 @@ chain_apis::read_only chain_plugin::get_read_only_api(const fc::microseconds& ht } -bool chain_plugin::accept_block(const signed_block_ptr& block, const block_id_type& id, const block_state_ptr& bsp ) { +bool chain_plugin::accept_block(const signed_block_ptr& block, const block_id_type& id, const block_state_legacy_ptr& bsp ) { return my->incoming_block_sync_method(block, id, bsp); } @@ -2036,7 +2006,7 @@ fc::variant read_only::get_block_info(const read_only::get_block_info_params& pa } fc::variant read_only::get_block_header_state(const get_block_header_state_params& params, const fc::time_point&) const { - block_state_ptr b; + block_state_legacy_ptr b; std::optional block_num; std::exception_ptr e; try { @@ -2054,13 +2024,13 @@ fc::variant read_only::get_block_header_state(const get_block_header_state_param EOS_ASSERT( b, unknown_block_exception, "Could not find reversible block: ${block}", ("block", params.block_num_or_id)); fc::variant vo; - fc::to_variant( static_cast(*b), vo ); + fc::to_variant( static_cast(*b), vo ); return vo; } void read_write::push_block(read_write::push_block_params&& params, next_function next) { try { - app().get_method()(std::make_shared( std::move(params) ), std::optional{}, block_state_ptr{}); + app().get_method()(std::make_shared( std::move(params) ), std::optional{}, block_state_legacy_ptr{}); } catch ( boost::interprocess::bad_alloc& ) { handle_db_exhaustion(); } catch ( const std::bad_alloc& ) { diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/account_query_db.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/account_query_db.hpp index ce95784319..2b360e28db 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/account_query_db.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/account_query_db.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include namespace eosio::chain_apis { @@ -40,7 +39,7 @@ namespace eosio::chain_apis { * uncommitted traces. * @param block */ - void commit_block(const chain::block_state_ptr& block ); + void commit_block( const chain::signed_block_ptr& block ); /** * parameters for the get_accounts_by_authorizers RPC diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index 512df8eb69..2a45273775 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -978,7 +978,7 @@ class chain_plugin : public plugin { chain_apis::read_write get_read_write_api(const fc::microseconds& http_max_response_time); chain_apis::read_only get_read_only_api(const fc::microseconds& http_max_response_time) const; - bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id, const chain::block_state_ptr& bsp ); + bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id, const chain::block_state_legacy_ptr& bsp ); void accept_transaction(const chain::packed_transaction_ptr& trx, chain::plugin_interface::next_function next); // Only call this after plugin_initialize()! diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/trx_finality_status_processing.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/trx_finality_status_processing.hpp index df1ec98f37..b092f38320 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/trx_finality_status_processing.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/trx_finality_status_processing.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include @@ -42,9 +41,9 @@ namespace eosio::chain_apis { void signal_applied_transaction( const chain::transaction_trace_ptr& trace, const chain::packed_transaction_ptr& ptrx ); - void signal_accepted_block( const chain::block_state_ptr& bsp ); + void signal_accepted_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ); - void signal_irreversible_block( const chain::block_state_ptr& bsp ); + void signal_irreversible_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ); void signal_block_start( uint32_t block_num ); diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp index ebad51a18a..7ffb041e0b 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/trx_retry_db.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include namespace eosio::chain_apis { @@ -64,12 +63,12 @@ class trx_retry_db { /** * Attach to chain accepted_block signal */ - void on_accepted_block(const chain::block_state_ptr& block ); + void on_accepted_block( uint32_t block_num ); /** * Attach to chain irreversible_block signal */ - void on_irreversible_block(const chain::block_state_ptr& block ); + void on_irreversible_block( const chain::signed_block_ptr& block ); private: std::unique_ptr _impl; diff --git a/plugins/chain_plugin/test/test_account_query_db.cpp b/plugins/chain_plugin/test/test_account_query_db.cpp index 25de9faf51..cd02c1627a 100644 --- a/plugins/chain_plugin/test/test_account_query_db.cpp +++ b/plugins/chain_plugin/test/test_account_query_db.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -38,8 +37,9 @@ BOOST_FIXTURE_TEST_CASE(newaccount_test, validating_tester) { try { auto aq_db = account_query_db(*control); //link aq_db to the `accepted_block` signal on the controller - auto c2 = control->accepted_block.connect([&](const block_state_ptr& blk) { - aq_db.commit_block( blk); + auto c2 = control->accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + aq_db.commit_block( block ); }); produce_blocks(10); @@ -63,8 +63,9 @@ BOOST_FIXTURE_TEST_CASE(updateauth_test, validating_tester) { try { auto aq_db = account_query_db(*control); //link aq_db to the `accepted_block` signal on the controller - auto c = control->accepted_block.connect([&](const block_state_ptr& blk) { - aq_db.commit_block( blk); + auto c = control->accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + aq_db.commit_block( block ); }); produce_blocks(10); @@ -97,8 +98,9 @@ BOOST_FIXTURE_TEST_CASE(updateauth_test_multi_threaded, validating_tester) { try auto aq_db = account_query_db(*control); //link aq_db to the `accepted_block` signal on the controller - auto c = control->accepted_block.connect([&](const block_state_ptr& blk) { - aq_db.commit_block( blk); + auto c = control->accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + aq_db.commit_block( block ); }); produce_blocks(10); @@ -149,8 +151,9 @@ BOOST_AUTO_TEST_CASE(future_fork_test) { try { auto aq_db = account_query_db(*node_a.control); //link aq_db to the `accepted_block` signal on the controller - auto c = node_a.control->accepted_block.connect([&](const block_state_ptr& blk) { - aq_db.commit_block( blk); + auto c = node_a.control->accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + aq_db.commit_block( block ); }); // create 10 blocks synced @@ -196,8 +199,9 @@ BOOST_AUTO_TEST_CASE(fork_test) { try { auto aq_db = account_query_db(*node_a.control); //link aq_db to the `accepted_block` signal on the controller - auto c = node_a.control->accepted_block.connect([&](const block_state_ptr& blk) { - aq_db.commit_block( blk); + auto c = node_a.control->accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + aq_db.commit_block( block ); }); // create 10 blocks synced diff --git a/plugins/chain_plugin/test/test_trx_finality_status_processing.cpp b/plugins/chain_plugin/test/test_trx_finality_status_processing.cpp index 79217590a4..770fe31e46 100644 --- a/plugins/chain_plugin/test/test_trx_finality_status_processing.cpp +++ b/plugins/chain_plugin/test/test_trx_finality_status_processing.cpp @@ -78,7 +78,7 @@ chain::block_id_type make_block_id( uint32_t block_num ) { return block_id; } -chain::transaction_trace_ptr make_transaction_trace( const packed_transaction_ptr trx, uint32_t block_number, const eosio::chain::block_state_ptr& bs_ptr, +chain::transaction_trace_ptr make_transaction_trace( const packed_transaction_ptr trx, uint32_t block_number, const eosio::chain::block_state_legacy_ptr& bs_ptr, chain::transaction_receipt_header::status_enum status = eosio::chain::transaction_receipt_header::executed ) { return std::make_shared(chain::transaction_trace{ trx->id(), @@ -113,7 +113,7 @@ auto make_block_state( uint32_t block_num ) { auto priv_key = get_private_key( block->producer, "active" ); auto pub_key = get_public_key( block->producer, "active" ); - auto prev = std::make_shared(); + auto prev = std::make_shared(); auto header_bmroot = chain::digest_type::hash( std::make_pair( block->digest(), prev->blockroot_merkle.get_root())); auto sig_digest = chain::digest_type::hash( std::make_pair( header_bmroot, prev->pending_schedule.schedule_hash )); block->producer_signature = priv_key.sign( sig_digest ); @@ -127,7 +127,7 @@ auto make_block_state( uint32_t block_num ) { result.emplace_back( k.sign( d )); return result; }; - chain::pending_block_header_state pbhs; + chain::pending_block_header_state_legacy pbhs; pbhs.producer = block->producer; pbhs.timestamp = block->timestamp; pbhs.previous = block->previous; @@ -136,7 +136,7 @@ auto make_block_state( uint32_t block_num ) { chain::block_signing_authority_v0{1, {{pub_key, 1}}}}}}; pbhs.active_schedule = schedule; pbhs.valid_block_signing_authority = chain::block_signing_authority_v0{1, {{pub_key, 1}}}; - auto bsp = std::make_shared( + auto bsp = std::make_shared( std::move( pbhs ), std::move( block ), deque(), @@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { using trx_deque = eosio::chain::deque< std::tuple< chain::transaction_trace_ptr, packed_transaction_ptr > >; uint32_t bn = 20; - auto add = [&bn, &status](trx_deque& trx_pairs, const eosio::chain::block_state_ptr& bs_ptr) { + auto add = [&bn, &status](trx_deque& trx_pairs, const eosio::chain::block_state_legacy_ptr& bs_ptr) { auto trx = make_unique_trx(fc::seconds(2)); auto trace = make_transaction_trace( trx, bn, bs_ptr); trx_pairs.push_back(std::tuple(trace, trx)); @@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { // Create speculative block to begin applying transactions locally status.signal_block_start(bn); - const eosio::chain::block_state_ptr no_bs; + const eosio::chain::block_state_legacy_ptr no_bs; add(trx_pairs_20, no_bs); add(trx_pairs_20, no_bs); @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { const auto block_20_time = set_now("2022-04-04", "04:44:44.500"); add(trx_pairs_20, bs_20); add(trx_pairs_20, bs_20); - status.signal_accepted_block(bs_20); + status.signal_accepted_block(bs_20->block, bs_20->id); cs = status.get_chain_state(); @@ -321,7 +321,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); add(trx_pairs_21, bs_21); - status.signal_accepted_block(bs_21); + status.signal_accepted_block(bs_21->block, bs_21->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_21->id); @@ -390,7 +390,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { status.signal_block_start(bn); add(trx_pairs_22, bs_22); - status.signal_accepted_block(bs_22); + status.signal_accepted_block(bs_22->block, bs_22->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_22->id); @@ -468,7 +468,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { status.signal_block_start(bn); add(trx_pairs_22_alt, bs_22_alt); - status.signal_accepted_block(bs_22_alt); + status.signal_accepted_block(bs_22_alt->block, bs_22_alt->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_22_alt->id); @@ -553,7 +553,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { status.signal_block_start(bn); add(trx_pairs_19, bs_19); - status.signal_accepted_block(bs_19); + status.signal_accepted_block(bs_19->block, bs_19->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_19->id); @@ -661,7 +661,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { status.signal_applied_transaction(trace, txn); } - status.signal_accepted_block(bs_19_alt); + status.signal_accepted_block(bs_19_alt->block, bs_19_alt->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_19_alt->id); @@ -750,7 +750,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { BOOST_REQUIRE(!ts); // irreversible - status.signal_irreversible_block(bs_19_alt); + status.signal_irreversible_block(bs_19_alt->block, bs_19_alt->id); cs = status.get_chain_state(); BOOST_CHECK(cs.head_id == bs_19_alt->id); @@ -834,7 +834,7 @@ BOOST_AUTO_TEST_CASE(trx_finality_status_logic) { try { namespace { using trx_deque = eosio::chain::deque< std::tuple< chain::transaction_trace_ptr, packed_transaction_ptr > >; - const eosio::chain::block_state_ptr no_bs; + const eosio::chain::block_state_legacy_ptr no_bs; struct block_frame { static uint32_t last_used_block_num; @@ -844,7 +844,7 @@ namespace { const std::string time; trx_deque pre_block; trx_deque block; - chain::block_state_ptr bs; + chain::block_state_legacy_ptr bs; std::string context; block_frame(trx_finality_status_processing& finality_status, const char* block_time, uint32_t block_num = 0) @@ -898,7 +898,7 @@ namespace { status.signal_applied_transaction(trace, txn); } - status.signal_accepted_block(bs); + status.signal_accepted_block(bs->block, bs->id); } void send_spec_block() { @@ -914,7 +914,7 @@ namespace { } private: - void verify(const trx_deque& trx_pairs, const chain::block_state_ptr& bs, uint32_t begin, uint32_t end) { + void verify(const trx_deque& trx_pairs, const chain::block_state_legacy_ptr& bs, uint32_t begin, uint32_t end) { if (end == std::numeric_limits::max()) { end = block.size(); } diff --git a/plugins/chain_plugin/test/test_trx_retry_db.cpp b/plugins/chain_plugin/test/test_trx_retry_db.cpp index f17f3cbf98..f9810b30bd 100644 --- a/plugins/chain_plugin/test/test_trx_retry_db.cpp +++ b/plugins/chain_plugin/test/test_trx_retry_db.cpp @@ -152,7 +152,7 @@ auto make_block_state( uint32_t block_num, std::vectorproducer, "active" ); auto pub_key = get_public_key( block->producer, "active" ); - auto prev = std::make_shared(); + auto prev = std::make_shared(); auto header_bmroot = chain::digest_type::hash( std::make_pair( block->digest(), prev->blockroot_merkle.get_root())); auto sig_digest = chain::digest_type::hash( std::make_pair( header_bmroot, prev->pending_schedule.schedule_hash )); block->producer_signature = priv_key.sign( sig_digest ); @@ -166,7 +166,7 @@ auto make_block_state( uint32_t block_num, std::vectorproducer; pbhs.timestamp = block->timestamp; pbhs.previous = block->previous; @@ -175,7 +175,7 @@ auto make_block_state( uint32_t block_num, std::vector( + auto bsp = std::make_shared( std::move( pbhs ), std::move( block ), deque(), @@ -276,8 +276,8 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // signal block, nothing should be expired as now has not changed auto bsp1 = make_block_state(1, {}); trx_retry.on_block_start(1); - trx_retry.on_accepted_block(bsp1); - trx_retry.on_irreversible_block(bsp1); + trx_retry.on_accepted_block(bsp1->block_num); + trx_retry.on_irreversible_block(bsp1->block); BOOST_CHECK(!trx_1_expired); BOOST_CHECK(!trx_2_expired); // increase time by 3 seconds to expire first @@ -286,8 +286,8 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // signal block, first transaction should expire auto bsp2 = make_block_state(2, {}); trx_retry.on_block_start(2); - trx_retry.on_accepted_block(bsp2); - trx_retry.on_irreversible_block(bsp2); + trx_retry.on_accepted_block(bsp2->block_num); + trx_retry.on_irreversible_block(bsp2->block); BOOST_CHECK(trx_1_expired); BOOST_CHECK(!trx_2_expired); // increase time by 2 seconds to expire second @@ -296,8 +296,8 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // signal block, second transaction should expire auto bsp3 = make_block_state(3, {}); trx_retry.on_block_start(3); - trx_retry.on_accepted_block(bsp3); - trx_retry.on_irreversible_block(bsp3); + trx_retry.on_accepted_block(bsp3->block_num); + trx_retry.on_irreversible_block(bsp3->block); BOOST_CHECK(trx_1_expired); BOOST_CHECK(trx_2_expired); BOOST_CHECK_EQUAL(0u, trx_retry.size()); @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // signal block, transaction 3 should be sent auto bsp4 = make_block_state(4, {}); trx_retry.on_block_start(4); - trx_retry.on_accepted_block(bsp4); + trx_retry.on_accepted_block(bsp4->block_num); BOOST_CHECK( get_id(transactions_acked.pop().second) == 3 ); BOOST_CHECK_EQUAL( 0u, transactions_acked.size() ); // increase time by 1 seconds, so trx_4 is sent @@ -337,7 +337,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // signal block, transaction 4 should be sent auto bsp5 = make_block_state(5, {}); trx_retry.on_block_start(5); - trx_retry.on_accepted_block(bsp5); + trx_retry.on_accepted_block(bsp5->block_num); BOOST_CHECK( get_id(transactions_acked.pop().second) == 4 ); BOOST_CHECK_EQUAL( 0u, transactions_acked.size() ); BOOST_CHECK(!trx_3_expired); @@ -347,10 +347,10 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp6 = make_block_state(6, {}); trx_retry.on_block_start(6); - trx_retry.on_accepted_block(bsp6); - trx_retry.on_irreversible_block(bsp4); - trx_retry.on_irreversible_block(bsp5); - trx_retry.on_irreversible_block(bsp6); + trx_retry.on_accepted_block(bsp6->block_num); + trx_retry.on_irreversible_block(bsp4->block); + trx_retry.on_irreversible_block(bsp5->block); + trx_retry.on_irreversible_block(bsp6->block); BOOST_CHECK(trx_3_expired); BOOST_CHECK(trx_4_expired); BOOST_CHECK_EQUAL(0u, trx_retry.size()); @@ -378,7 +378,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // not in block 7, so not returned to user auto bsp7 = make_block_state(7, {}); trx_retry.on_block_start(7); - trx_retry.on_accepted_block(bsp7); + trx_retry.on_accepted_block(bsp7->block_num); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(!trx_6_variant); // 5,6 in block 8 @@ -390,7 +390,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { trx_retry.on_applied_transaction(trace_5, trx_5); trx_retry.on_applied_transaction(trace_6, trx_6); auto bsp8 = make_block_state(8, {trx_5, trx_6}); - trx_retry.on_accepted_block(bsp8); + trx_retry.on_accepted_block(bsp8->block_num); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(!trx_6_variant); // need 2 blocks before 6 returned to user @@ -398,14 +398,14 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp9 = make_block_state(9, {}); trx_retry.on_block_start(9); - trx_retry.on_accepted_block(bsp9); + trx_retry.on_accepted_block(bsp9->block_num); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(!trx_6_variant); pnow += boost::posix_time::seconds(1); // new block, new time fc::mock_time_traits::set_now(pnow); auto bsp10 = make_block_state(10, {}); trx_retry.on_block_start(10); - trx_retry.on_accepted_block(bsp10); + trx_retry.on_accepted_block(bsp10->block_num); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(trx_6_variant); // now signal lib for trx_6 @@ -413,13 +413,13 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp11 = make_block_state(11, {}); trx_retry.on_block_start(11); - trx_retry.on_accepted_block(bsp11); + trx_retry.on_accepted_block(bsp11->block_num); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(trx_6_variant); - trx_retry.on_irreversible_block(bsp7); + trx_retry.on_irreversible_block(bsp7->block); BOOST_CHECK(!trx_5_variant); BOOST_CHECK(trx_6_variant); - trx_retry.on_irreversible_block(bsp8); + trx_retry.on_irreversible_block(bsp8->block); BOOST_CHECK(trx_5_variant); BOOST_CHECK(trx_6_variant); BOOST_CHECK_EQUAL(0u, trx_retry.size()); @@ -456,7 +456,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { // not in block 12 auto bsp12 = make_block_state(12, {}); trx_retry.on_block_start(12); - trx_retry.on_accepted_block(bsp12); + trx_retry.on_accepted_block(bsp12->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { trx_retry.on_applied_transaction(trace_8, trx_8); trx_retry.on_applied_transaction(trace_9, trx_9); auto bsp13 = make_block_state(13, {trx_7, trx_8, trx_9}); - trx_retry.on_accepted_block(bsp13); + trx_retry.on_accepted_block(bsp13->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -480,7 +480,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp14 = make_block_state(14, {}); trx_retry.on_block_start(14); - trx_retry.on_accepted_block(bsp14); + trx_retry.on_accepted_block(bsp14->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -488,7 +488,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp15 = make_block_state(15, {}); trx_retry.on_block_start(15); - trx_retry.on_accepted_block(bsp15); + trx_retry.on_accepted_block(bsp15->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -500,14 +500,14 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { BOOST_CHECK_EQUAL(3u, trx_retry.size()); // now produce an empty 13 auto bsp13b = make_block_state(13, {}); // now 13 has no traces - trx_retry.on_accepted_block(bsp13b); + trx_retry.on_accepted_block(bsp13b->block_num); // produced another empty block pnow += boost::posix_time::seconds(1); // new block, new time fc::mock_time_traits::set_now(pnow); trx_retry.on_block_start(14); // now produce an empty 14 auto bsp14b = make_block_state(14, {}); // empty - trx_retry.on_accepted_block(bsp14b); + trx_retry.on_accepted_block(bsp14b->block_num); // produce block with 7,8 trx_retry.on_block_start(15); auto trace_7b = make_transaction_trace( trx_7, 15); @@ -515,13 +515,13 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { trx_retry.on_applied_transaction(trace_7b, trx_7); trx_retry.on_applied_transaction(trace_8b, trx_8); auto bsp15b = make_block_state(15, {trx_7, trx_8}); - trx_retry.on_accepted_block(bsp15b); + trx_retry.on_accepted_block(bsp15b->block_num); // need 3 blocks before 8 returned to user pnow += boost::posix_time::seconds(1); // new block, new time fc::mock_time_traits::set_now(pnow); auto bsp16 = make_block_state(16, {}); trx_retry.on_block_start(16); - trx_retry.on_accepted_block(bsp16); + trx_retry.on_accepted_block(bsp16->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -529,7 +529,7 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp17 = make_block_state(17, {}); trx_retry.on_block_start(17); - trx_retry.on_accepted_block(bsp17); + trx_retry.on_accepted_block(bsp17->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(!trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -537,20 +537,20 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp18 = make_block_state(18, {}); trx_retry.on_block_start(18); - trx_retry.on_accepted_block(bsp18); + trx_retry.on_accepted_block(bsp18->block_num); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(!trx_9_expired); - trx_retry.on_irreversible_block(bsp9); - trx_retry.on_irreversible_block(bsp10); - trx_retry.on_irreversible_block(bsp11); - trx_retry.on_irreversible_block(bsp12); - trx_retry.on_irreversible_block(bsp13b); - trx_retry.on_irreversible_block(bsp14b); + trx_retry.on_irreversible_block(bsp9->block); + trx_retry.on_irreversible_block(bsp10->block); + trx_retry.on_irreversible_block(bsp11->block); + trx_retry.on_irreversible_block(bsp12->block); + trx_retry.on_irreversible_block(bsp13b->block); + trx_retry.on_irreversible_block(bsp14b->block); BOOST_CHECK(!trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(!trx_9_expired); - trx_retry.on_irreversible_block(bsp15b); + trx_retry.on_irreversible_block(bsp15b->block); BOOST_CHECK(trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -559,12 +559,12 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp19 = make_block_state(19, {}); trx_retry.on_block_start(19); - trx_retry.on_accepted_block(bsp19); - trx_retry.on_irreversible_block(bsp15); - trx_retry.on_irreversible_block(bsp16); - trx_retry.on_irreversible_block(bsp17); - trx_retry.on_irreversible_block(bsp18); - trx_retry.on_irreversible_block(bsp19); + trx_retry.on_accepted_block(bsp19->block_num); + trx_retry.on_irreversible_block(bsp15->block); + trx_retry.on_irreversible_block(bsp16->block); + trx_retry.on_irreversible_block(bsp17->block); + trx_retry.on_irreversible_block(bsp18->block); + trx_retry.on_irreversible_block(bsp19->block); BOOST_CHECK(trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(!trx_9_expired); @@ -572,12 +572,12 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { fc::mock_time_traits::set_now(pnow); auto bsp20 = make_block_state(20, {}); trx_retry.on_block_start(20); - trx_retry.on_accepted_block(bsp20); + trx_retry.on_accepted_block(bsp20->block_num); // waits for LIB BOOST_CHECK(trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(!trx_9_expired); - trx_retry.on_irreversible_block(bsp20); + trx_retry.on_irreversible_block(bsp20->block); BOOST_CHECK(trx_7_variant); BOOST_CHECK(trx_8_variant); BOOST_CHECK(trx_9_expired); @@ -607,14 +607,14 @@ BOOST_AUTO_TEST_CASE(trx_retry_logic) { trx_retry.on_applied_transaction(trace_10, trx_10); trx_retry.on_applied_transaction(trace_11, trx_11); auto bsp21 = make_block_state(21, {trx_10, trx_11}); - trx_retry.on_accepted_block(bsp21); + trx_retry.on_accepted_block(bsp21->block_num); BOOST_CHECK(trx_10_variant); BOOST_CHECK(!trx_11_variant); pnow += boost::posix_time::seconds(1); // new block, new time fc::mock_time_traits::set_now(pnow); auto bsp22 = make_block_state(22, {}); trx_retry.on_block_start(22); - trx_retry.on_accepted_block(bsp22); + trx_retry.on_accepted_block(bsp22->block_num); BOOST_CHECK(trx_10_variant); BOOST_CHECK(trx_11_variant); BOOST_CHECK_EQUAL(0u, trx_retry.size()); diff --git a/plugins/chain_plugin/trx_finality_status_processing.cpp b/plugins/chain_plugin/trx_finality_status_processing.cpp index c95a0c774c..3ac42dbc3f 100644 --- a/plugins/chain_plugin/trx_finality_status_processing.cpp +++ b/plugins/chain_plugin/trx_finality_status_processing.cpp @@ -15,7 +15,7 @@ namespace eosio::chain_apis { void signal_applied_transaction( const chain::transaction_trace_ptr& trace, const chain::packed_transaction_ptr& ptrx ); - void signal_accepted_block( const chain::block_state_ptr& bsp ); + void signal_accepted_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ); void handle_rollback(); @@ -47,10 +47,10 @@ namespace eosio::chain_apis { trx_finality_status_processing::~trx_finality_status_processing() = default; - void trx_finality_status_processing::signal_irreversible_block( const chain::block_state_ptr& bsp ) { + void trx_finality_status_processing::signal_irreversible_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { try { - _my->_irr_block_id = bsp->id; - _my->_irr_block_timestamp = bsp->block->timestamp; + _my->_irr_block_id = id; + _my->_irr_block_timestamp = block->timestamp; } FC_LOG_AND_DROP(("Failed to signal irreversible block for finality status")); } @@ -67,9 +67,9 @@ namespace eosio::chain_apis { } FC_LOG_AND_DROP(("Failed to signal applied transaction for finality status")); } - void trx_finality_status_processing::signal_accepted_block( const chain::block_state_ptr& bsp ) { + void trx_finality_status_processing::signal_accepted_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { try { - _my->signal_accepted_block(bsp); + _my->signal_accepted_block(block, id); } FC_LOG_AND_DROP(("Failed to signal accepted block for finality status")); } @@ -139,14 +139,14 @@ namespace eosio::chain_apis { } } - void trx_finality_status_processing_impl::signal_accepted_block( const chain::block_state_ptr& bsp ) { + void trx_finality_status_processing_impl::signal_accepted_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { // if this block had any transactions, then we have processed everything we need to already - if (bsp->id == _head_block_id) { + if (id == _head_block_id) { return; } - _head_block_id = bsp->id; - _head_block_timestamp = bsp->block->timestamp; + _head_block_id = id; + _head_block_timestamp = block->timestamp; const auto head_block_num = chain::block_header::num_from_id(_head_block_id); if (head_block_num <= _last_proc_block_num) { diff --git a/plugins/chain_plugin/trx_retry_db.cpp b/plugins/chain_plugin/trx_retry_db.cpp index 9ba86794d4..1febd72513 100644 --- a/plugins/chain_plugin/trx_retry_db.cpp +++ b/plugins/chain_plugin/trx_retry_db.cpp @@ -161,15 +161,15 @@ struct trx_retry_db_impl { rollback_to( block_num ); } - void on_accepted_block(const chain::block_state_ptr& bsp ) { + void on_accepted_block( uint32_t block_num ) { // good time to perform processing - ack_ready_trxs_by_block_num( bsp->block_num ); + ack_ready_trxs_by_block_num( block_num ); retry_trxs(); } - void on_irreversible_block(const chain::block_state_ptr& bsp ) { - ack_ready_trxs_by_lib( bsp->block_num ); - clear_expired( bsp->block->timestamp ); + void on_irreversible_block( const chain::signed_block_ptr& block ) { + ack_ready_trxs_by_lib( block->block_num() ); + clear_expired( block->timestamp ); } private: @@ -321,13 +321,13 @@ void trx_retry_db::on_block_start( uint32_t block_num ) { } FC_LOG_AND_DROP(("trx retry block_start ERROR")); } -void trx_retry_db::on_accepted_block(const chain::block_state_ptr& block ) { +void trx_retry_db::on_accepted_block( uint32_t block_num ) { try { - _impl->on_accepted_block(block); + _impl->on_accepted_block(block_num); } FC_LOG_AND_DROP(("trx retry accepted_block ERROR")); } -void trx_retry_db::on_irreversible_block(const chain::block_state_ptr& block ) { +void trx_retry_db::on_irreversible_block(const chain::signed_block_ptr& block) { try { _impl->on_irreversible_block(block); } FC_LOG_AND_DROP(("trx retry irreversible_block ERROR")); diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index a103d0ed06..63d5e3532b 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -444,10 +444,13 @@ namespace eosio { class net_plugin_impl : public std::enable_shared_from_this, public auto_bp_peering::bp_connection_manager { public: + uint16_t thread_pool_size = 4; + eosio::chain::named_thread_pool thread_pool; + std::atomic current_connection_id{0}; unique_ptr< sync_manager > sync_master; - unique_ptr< dispatch_manager > dispatcher; + dispatch_manager dispatcher {thread_pool.get_executor()}; connections_manager connections; /** @@ -488,11 +491,11 @@ namespace eosio { alignas(hardware_destructive_interference_size) fc::mutex expire_timer_mtx; - unique_ptr expire_timer GUARDED_BY(expire_timer_mtx); + boost::asio::steady_timer expire_timer GUARDED_BY(expire_timer_mtx) {thread_pool.get_executor()}; alignas(hardware_destructive_interference_size) fc::mutex keepalive_timer_mtx; - unique_ptr keepalive_timer GUARDED_BY(keepalive_timer_mtx); + boost::asio::steady_timer keepalive_timer GUARDED_BY(keepalive_timer_mtx) {thread_pool.get_executor()}; alignas(hardware_destructive_interference_size) std::atomic in_shutdown{false}; @@ -500,9 +503,6 @@ namespace eosio { alignas(hardware_destructive_interference_size) compat::channels::transaction_ack::channel_type::handle incoming_transaction_ack_subscription; - uint16_t thread_pool_size = 4; - eosio::chain::named_thread_pool thread_pool; - boost::asio::deadline_timer accept_error_timer{thread_pool.get_executor()}; @@ -528,11 +528,11 @@ namespace eosio { uint32_t get_chain_lib_num() const; uint32_t get_chain_head_num() const; - void on_accepted_block_header( const block_state_ptr& bs ); - void on_accepted_block( const block_state_ptr& bs ); + void on_accepted_block_header( const signed_block_ptr& block, const block_id_type& id ); + void on_accepted_block(); void transaction_ack(const std::pair&); - void on_irreversible_block( const block_state_ptr& block ); + void on_irreversible_block( const block_id_type& id, uint32_t block_num ); void start_expire_timer(); void start_monitors(); @@ -1098,7 +1098,7 @@ namespace eosio { // returns calculated number of blocks combined latency uint32_t calc_block_latency(); - void process_signed_block( const block_id_type& id, signed_block_ptr block, block_state_ptr bsp ); + void process_signed_block( const block_id_type& id, signed_block_ptr block, block_state_legacy_ptr bsp ); fc::variant_object get_logger_variant() const { fc::mutable_variant_object mvo; @@ -1452,7 +1452,7 @@ namespace eosio { conn_node_id = fc::sha256(); } if( has_last_req && !shutdown ) { - my_impl->dispatcher->retry_fetch( shared_from_this() ); + my_impl->dispatcher.retry_fetch( shared_from_this() ); } peer_lib_num = 0; peer_requested.reset(); @@ -1966,7 +1966,7 @@ namespace eosio { // called from connection strand void connection::fetch_timeout( boost::system::error_code ec ) { if( !ec ) { - my_impl->dispatcher->retry_fetch( shared_from_this() ); + my_impl->dispatcher.retry_fetch( shared_from_this() ); } else if( ec != boost::asio::error::operation_aborted ) { // don't log on operation_aborted, called on destroy peer_elog( this, "setting timer for fetch request got error ${ec}", ("ec", ec.message() ) ); } @@ -2124,8 +2124,8 @@ namespace eosio { void sync_manager::request_next_chunk( const connection_ptr& conn ) REQUIRES(sync_mtx) { auto chain_info = my_impl->get_chain_info(); - fc_dlog( logger, "sync_last_requested_num: ${r}, sync_next_expected_num: ${e}, sync_known_lib_num: ${k}, sync_req_span: ${s}, head: ${h}", - ("r", sync_last_requested_num)("e", sync_next_expected_num)("k", sync_known_lib_num)("s", sync_req_span)("h", chain_info.head_num) ); + fc_dlog( logger, "sync_last_requested_num: ${r}, sync_next_expected_num: ${e}, sync_known_lib_num: ${k}, sync_req_span: ${s}, head: ${h}, lib: ${lib}", + ("r", sync_last_requested_num)("e", sync_next_expected_num)("k", sync_known_lib_num)("s", sync_req_span)("h", chain_info.head_num)("lib", chain_info.lib_num) ); if( chain_info.head_num + sync_req_span < sync_last_requested_num && sync_source && sync_source->current() ) { fc_dlog( logger, "ignoring request, head is ${h} last req = ${r}, sync_next_expected_num: ${e}, sync_known_lib_num: ${k}, sync_req_span: ${s}, source connection ${c}", @@ -2169,8 +2169,8 @@ namespace eosio { sync_last_requested_num = end; sync_source = new_sync_source; request_sent = true; - new_sync_source->strand.post( [new_sync_source, start, end, head_num=chain_info.head_num]() { - peer_ilog( new_sync_source, "requesting range ${s} to ${e}, head ${h}", ("s", start)("e", end)("h", head_num) ); + new_sync_source->strand.post( [new_sync_source, start, end, head_num=chain_info.head_num, lib=chain_info.lib_num]() { + peer_ilog( new_sync_source, "requesting range ${s} to ${e}, head ${h}, lib ${lib}", ("s", start)("e", end)("h", head_num)("lib", lib) ); new_sync_source->request_sync_blocks( start, end ); } ); } @@ -2216,8 +2216,10 @@ namespace eosio { if( sync_state != lib_catchup ) { set_state( lib_catchup ); + sync_next_expected_num = chain_info.lib_num + 1; + } else { + sync_next_expected_num = std::max( chain_info.lib_num + 1, sync_next_expected_num ); } - sync_next_expected_num = std::max( chain_info.lib_num + 1, sync_next_expected_num ); request_next_chunk( c ); } @@ -2403,7 +2405,7 @@ namespace eosio { const block_id_type& id = msg.known_blocks.ids.back(); peer_ilog( c, "notice_message, pending ${p}, blk_num ${n}, id ${id}...", ("p", msg.known_blocks.pending)("n", block_header::num_from_id(id))("id",id.str().substr(8,16)) ); - if( !my_impl->dispatcher->have_block( id ) ) { + if( !my_impl->dispatcher.have_block( id ) ) { verify_catchup( c, msg.known_blocks.pending, id ); } else { // we already have the block, so update peer with our view of the world @@ -2425,11 +2427,10 @@ namespace eosio { // called from connection strand void sync_manager::rejected_block( const connection_ptr& c, uint32_t blk_num ) { c->block_status_monitor_.rejected(); + // reset sync on rejected block fc::unique_lock g( sync_mtx ); sync_last_requested_num = 0; - if (blk_num < sync_next_expected_num) { - sync_next_expected_num = my_impl->get_chain_lib_num(); - } + sync_next_expected_num = my_impl->get_chain_lib_num() + 1; if( c->block_status_monitor_.max_events_violated()) { peer_wlog( c, "block ${bn} not accepted, closing connection", ("bn", blk_num) ); sync_source.reset(); @@ -2504,7 +2505,11 @@ namespace eosio { c->sync_wait(); } - sync_next_expected_num = blk_num + 1; + if (sync_last_requested_num == 0) { // block was rejected + sync_next_expected_num = my_impl->get_chain_lib_num() + 1; + } else { + sync_next_expected_num = blk_num + 1; + } } uint32_t head = my_impl->get_chain_head_num(); @@ -3057,7 +3062,7 @@ namespace eosio { const block_id_type blk_id = bh.calculate_id(); const uint32_t blk_num = last_received_block_num = block_header::num_from_id(blk_id); // don't add_peer_block because we have not validated this block header yet - if( my_impl->dispatcher->have_block( blk_id ) ) { + if( my_impl->dispatcher.have_block( blk_id ) ) { peer_dlog( this, "canceling wait, already received block ${num}, id ${id}...", ("num", blk_num)("id", blk_id.str().substr(8,16)) ); my_impl->sync_master->sync_recv_block( shared_from_this(), blk_id, blk_num, false ); @@ -3158,8 +3163,8 @@ namespace eosio { } return true; } - bool have_trx = my_impl->dispatcher->have_txn( ptr->id() ); - my_impl->dispatcher->add_peer_txn( ptr->id(), ptr->expiration(), connection_id ); + bool have_trx = my_impl->dispatcher.have_txn( ptr->id() ); + my_impl->dispatcher.add_peer_txn( ptr->id(), ptr->expiration(), connection_id ); if( have_trx ) { peer_dlog( this, "got a duplicate transaction - dropping" ); @@ -3173,18 +3178,6 @@ namespace eosio { void net_plugin_impl::plugin_shutdown() { in_shutdown = true; - connections.stop_conn_timers(); - { - fc::lock_guard g( expire_timer_mtx ); - if( expire_timer ) - expire_timer->cancel(); - } - { - fc::lock_guard g( keepalive_timer_mtx ); - if( keepalive_timer ) - keepalive_timer->cancel(); - } - connections.close_all(); thread_pool.stop(); } @@ -3564,7 +3557,7 @@ namespace eosio { case catch_up: break; case normal: { - my_impl->dispatcher->recv_notice( shared_from_this(), msg, false ); + my_impl->dispatcher.recv_notice( shared_from_this(), msg, false ); } } @@ -3588,7 +3581,7 @@ namespace eosio { break; } case normal : { - my_impl->dispatcher->recv_notice( shared_from_this(), msg, false ); + my_impl->dispatcher.recv_notice( shared_from_this(), msg, false ); break; } default: { @@ -3694,19 +3687,19 @@ namespace eosio { // called from connection strand void connection::handle_message( const block_id_type& id, signed_block_ptr ptr ) { // post to dispatcher strand so that we don't have multiple threads validating the block header - my_impl->dispatcher->strand.post([id, c{shared_from_this()}, ptr{std::move(ptr)}, cid=connection_id]() mutable { + my_impl->dispatcher.strand.post([id, c{shared_from_this()}, ptr{std::move(ptr)}, cid=connection_id]() mutable { controller& cc = my_impl->chain_plug->chain(); // may have come in on a different connection and posted into dispatcher strand before this one - if( my_impl->dispatcher->have_block( id ) || cc.fetch_block_state_by_id( id ) ) { // thread-safe - my_impl->dispatcher->add_peer_block( id, c->connection_id ); + if( my_impl->dispatcher.have_block( id ) || cc.fetch_block_state_by_id( id ) ) { // thread-safe + my_impl->dispatcher.add_peer_block( id, c->connection_id ); c->strand.post( [c, id]() { my_impl->sync_master->sync_recv_block( c, id, block_header::num_from_id(id), false ); }); return; } - block_state_ptr bsp; + block_state_legacy_ptr bsp; bool exception = false; try { // this may return null if block is not immediately ready to be processed @@ -3723,7 +3716,7 @@ namespace eosio { if( exception ) { c->strand.post( [c, id, blk_num=ptr->block_num()]() { my_impl->sync_master->rejected_block( c, blk_num ); - my_impl->dispatcher->rejected_block( id ); + my_impl->dispatcher.rejected_block( id ); }); return; } @@ -3734,8 +3727,8 @@ namespace eosio { if( block_num != 0 ) { fc_dlog( logger, "validated block header, broadcasting immediately, connection ${cid}, blk num = ${num}, id = ${id}", ("cid", cid)("num", block_num)("id", bsp->id) ); - my_impl->dispatcher->add_peer_block( bsp->id, cid ); // no need to send back to sender - my_impl->dispatcher->bcast_block( bsp->block, bsp->id ); + my_impl->dispatcher.add_peer_block( bsp->id, cid ); // no need to send back to sender + my_impl->dispatcher.bcast_block( bsp->block, bsp->id ); } app().executor().post(priority::medium, exec_queue::read_write, [ptr{std::move(ptr)}, bsp{std::move(bsp)}, id, c{std::move(c)}]() mutable { @@ -3750,17 +3743,18 @@ namespace eosio { } // called from application thread - void connection::process_signed_block( const block_id_type& blk_id, signed_block_ptr block, block_state_ptr bsp ) { + void connection::process_signed_block( const block_id_type& blk_id, signed_block_ptr block, block_state_legacy_ptr bsp ) { controller& cc = my_impl->chain_plug->chain(); uint32_t blk_num = block_header::num_from_id(blk_id); // use c in this method instead of this to highlight that all methods called on c-> must be thread safe connection_ptr c = shared_from_this(); + uint32_t lib = cc.last_irreversible_block_num(); try { - if( blk_num <= cc.last_irreversible_block_num() || cc.fetch_block_by_id(blk_id) ) { + if( blk_num <= lib || cc.fetch_block_by_id(blk_id) ) { c->strand.post( [sync_master = my_impl->sync_master.get(), - dispatcher = my_impl->dispatcher.get(), c, blk_id, blk_num]() { - dispatcher->add_peer_block( blk_id, c->connection_id ); + &dispatcher = my_impl->dispatcher, c, blk_id, blk_num]() { + dispatcher.add_peer_block( blk_id, c->connection_id ); sync_master->sync_recv_block( c, blk_id, blk_num, true ); }); return; @@ -3774,7 +3768,7 @@ namespace eosio { fc::microseconds age( fc::time_point::now() - block->timestamp); fc_dlog( logger, "received signed_block: #${n} block age in secs = ${age}, connection ${cid}, ${v}", - ("n", blk_num)("age", age.to_seconds())("cid", c->connection_id)("v", bsp ? "pre-validated" : "validation pending") ); + ("n", blk_num)("age", age.to_seconds())("cid", c->connection_id)("v", bsp ? "pre-validated" : "validation pending")("lib", lib) ); go_away_reason reason = no_reason; bool accepted = false; @@ -3805,12 +3799,12 @@ namespace eosio { if( accepted ) { ++unique_blocks_rcvd_count; - boost::asio::post( my_impl->thread_pool.get_executor(), [dispatcher = my_impl->dispatcher.get(), c, blk_id, blk_num]() { + boost::asio::post( my_impl->thread_pool.get_executor(), [&dispatcher = my_impl->dispatcher, c, blk_id, blk_num]() { fc_dlog( logger, "accepted signed_block : #${n} ${id}...", ("n", blk_num)("id", blk_id.str().substr(8,16)) ); - dispatcher->add_peer_block( blk_id, c->connection_id ); + dispatcher.add_peer_block( blk_id, c->connection_id ); while (true) { // attempt previously unlinkable blocks where prev_unlinkable->block->previous == blk_id - unlinkable_block_state prev_unlinkable = dispatcher->pop_possible_linkable_block(blk_id); + unlinkable_block_state prev_unlinkable = dispatcher.pop_possible_linkable_block(blk_id); if (!prev_unlinkable.block) break; fc_dlog( logger, "retrying previous unlinkable block #${n} ${id}...", @@ -3821,21 +3815,21 @@ namespace eosio { }); } }); - c->strand.post( [sync_master = my_impl->sync_master.get(), dispatcher = my_impl->dispatcher.get(), c, blk_id, blk_num]() { - dispatcher->recv_block( c, blk_id, blk_num ); + c->strand.post( [sync_master = my_impl->sync_master.get(), &dispatcher = my_impl->dispatcher, c, blk_id, blk_num]() { + dispatcher.recv_block( c, blk_id, blk_num ); sync_master->sync_recv_block( c, blk_id, blk_num, true ); }); } else { - c->strand.post( [sync_master = my_impl->sync_master.get(), dispatcher = my_impl->dispatcher.get(), c, + c->strand.post( [sync_master = my_impl->sync_master.get(), &dispatcher = my_impl->dispatcher, c, block{std::move(block)}, blk_id, blk_num, reason]() mutable { if( reason == unlinkable || reason == no_reason ) { - dispatcher->add_unlinkable_block( std::move(block), blk_id ); + dispatcher.add_unlinkable_block( std::move(block), blk_id ); } // reason==no_reason means accept_block() return false because we are producing, don't call rejected_block which sends handshake if( reason != no_reason ) { sync_master->rejected_block( c, blk_num ); } - dispatcher->rejected_block( blk_id ); + dispatcher.rejected_block( blk_id ); }); } } @@ -3844,8 +3838,8 @@ namespace eosio { void net_plugin_impl::start_expire_timer() { if( in_shutdown ) return; fc::lock_guard g( expire_timer_mtx ); - expire_timer->expires_from_now( txn_exp_period); - expire_timer->async_wait( [my = shared_from_this()]( boost::system::error_code ec ) { + expire_timer.expires_from_now( txn_exp_period); + expire_timer.async_wait( [my = shared_from_this()]( boost::system::error_code ec ) { if( !ec ) { my->expire(); } else { @@ -3860,8 +3854,8 @@ namespace eosio { void net_plugin_impl::ticker() { if( in_shutdown ) return; fc::lock_guard g( keepalive_timer_mtx ); - keepalive_timer->expires_from_now(keepalive_interval); - keepalive_timer->async_wait( [my = shared_from_this()]( boost::system::error_code ec ) { + keepalive_timer.expires_from_now(keepalive_interval); + keepalive_timer.async_wait( [my = shared_from_this()]( boost::system::error_code ec ) { my->ticker(); if( ec ) { if( my->in_shutdown ) return; @@ -3880,10 +3874,6 @@ namespace eosio { } void net_plugin_impl::start_monitors() { - { - fc::lock_guard g( expire_timer_mtx ); - expire_timer = std::make_unique( my_impl->thread_pool.get_executor() ); - } connections.start_conn_timers(); start_expire_timer(); } @@ -3891,44 +3881,44 @@ namespace eosio { void net_plugin_impl::expire() { auto now = time_point::now(); uint32_t lib_num = get_chain_lib_num(); - dispatcher->expire_blocks( lib_num ); - dispatcher->expire_txns(); + dispatcher.expire_blocks( lib_num ); + dispatcher.expire_txns(); fc_dlog( logger, "expire_txns ${n}us", ("n", time_point::now() - now) ); start_expire_timer(); } // called from application thread - void net_plugin_impl::on_accepted_block_header(const block_state_ptr& bs) { + void net_plugin_impl::on_accepted_block_header(const signed_block_ptr& block, const block_id_type& id) { update_chain_info(); - dispatcher->strand.post([bs]() { - fc_dlog(logger, "signaled accepted_block_header, blk num = ${num}, id = ${id}", ("num", bs->block_num)("id", bs->id)); - my_impl->dispatcher->bcast_block(bs->block, bs->id); + dispatcher.strand.post([block, id]() { + fc_dlog(logger, "signaled accepted_block_header, blk num = ${num}, id = ${id}", ("num", block->block_num())("id", id)); + my_impl->dispatcher.bcast_block(block, id); }); } - void net_plugin_impl::on_accepted_block(const block_state_ptr& ) { + void net_plugin_impl::on_accepted_block() { on_pending_schedule(chain_plug->chain().pending_producers()); on_active_schedule(chain_plug->chain().active_producers()); } // called from application thread - void net_plugin_impl::on_irreversible_block( const block_state_ptr& block) { - fc_dlog( logger, "on_irreversible_block, blk num = ${num}, id = ${id}", ("num", block->block_num)("id", block->id) ); + void net_plugin_impl::on_irreversible_block( const block_id_type& id, uint32_t block_num) { + fc_dlog( logger, "on_irreversible_block, blk num = ${num}, id = ${id}", ("num", block_num)("id", id) ); update_chain_info(); } // called from application thread void net_plugin_impl::transaction_ack(const std::pair& results) { - boost::asio::post( my_impl->thread_pool.get_executor(), [dispatcher = my_impl->dispatcher.get(), results]() { + boost::asio::post( my_impl->thread_pool.get_executor(), [&dispatcher = my_impl->dispatcher, results]() { const auto& id = results.second->id(); if (results.first) { fc_dlog( logger, "signaled NACK, trx-id = ${id} : ${why}", ("id", id)( "why", results.first->to_detail_string() ) ); - dispatcher->rejected_transaction(results.second); + dispatcher.rejected_transaction(results.second); } else { fc_dlog( logger, "signaled ACK, trx-id = ${id}", ("id", id) ); - dispatcher->bcast_transaction(results.second); + dispatcher.bcast_transaction(results.second); } }); } @@ -4266,8 +4256,6 @@ namespace eosio { app().quit(); } ); - dispatcher = std::make_unique( my_impl->thread_pool.get_executor() ); - if( !p2p_accept_transactions && p2p_addresses.size() ) { fc_ilog( logger, "\n" "***********************************\n" @@ -4301,23 +4289,20 @@ namespace eosio { { chain::controller& cc = chain_plug->chain(); - cc.accepted_block_header.connect( [my = shared_from_this()]( const block_state_ptr& s ) { - my->on_accepted_block_header( s ); + cc.accepted_block_header.connect( [my = shared_from_this()]( const block_signal_params& t ) { + const auto& [ block, id ] = t; + my->on_accepted_block_header( block, id ); } ); - cc.accepted_block.connect( [my = shared_from_this()]( const block_state_ptr& s ) { - my->on_accepted_block( s ); + cc.accepted_block.connect( [my = shared_from_this()]( const block_signal_params& t ) { + my->on_accepted_block(); } ); - cc.irreversible_block.connect( [my = shared_from_this()]( const block_state_ptr& s ) { - my->on_irreversible_block( s ); + cc.irreversible_block.connect( [my = shared_from_this()]( const block_signal_params& t ) { + const auto& [ block, id ] = t; + my->on_irreversible_block( id, block->block_num() ); } ); } - { - fc::lock_guard g( keepalive_timer_mtx ); - keepalive_timer = std::make_unique( thread_pool.get_executor() ); - } - incoming_transaction_ack_subscription = app().get_channel().subscribe( [this](auto&& t) { transaction_ack(std::forward(t)); }); @@ -4771,4 +4756,4 @@ namespace eosio { update_p2p_connection_metrics({num_peers+num_bp_peers, num_clients, std::move(per_connection)}); start_conn_timer( connector_period, {}, timer_type::stats ); } -} // namespace eosio \ No newline at end of file +} // namespace eosio diff --git a/plugins/producer_api_plugin/producer_api_plugin.cpp b/plugins/producer_api_plugin/producer_api_plugin.cpp index cd59645a0b..6f86fdd3a6 100644 --- a/plugins/producer_api_plugin/producer_api_plugin.cpp +++ b/plugins/producer_api_plugin/producer_api_plugin.cpp @@ -23,7 +23,7 @@ using namespace eosio; #define CALL_WITH_400(api_name, category, api_handle, call_name, INVOKE, http_response_code) \ {std::string("/v1/" #api_name "/" #call_name), \ api_category::category, \ - [&http, &producer](string&&, string&& body, url_response_callback&& cb) mutable { \ + [&producer](string&&, string&& body, url_response_callback&& cb) mutable { \ try { \ INVOKE \ cb(http_response_code, fc::variant(result)); \ @@ -63,6 +63,7 @@ using namespace eosio; auto result = api_handle.call_name(std::move(params)); #define INVOKE_R_R_D(api_handle, call_name, in_param) \ + auto& http = app().get_plugin(); \ const fc::microseconds http_max_response_time = http.get_max_response_time(); \ auto deadline = http_max_response_time == fc::microseconds::maximum() ? fc::time_point::maximum() \ : fc::time_point::now() + http_max_response_time; \ @@ -91,7 +92,6 @@ void producer_api_plugin::plugin_startup() { ilog("starting producer_api_plugin"); // lifetime of plugin is lifetime of application auto& producer = app().get_plugin(); - auto& http = app().get_plugin(); app().get_plugin().add_api({ CALL_WITH_400(producer, producer_ro, producer, paused, diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 4ab1e39634..ee4229d653 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -397,13 +397,12 @@ class producer_plugin_impl : public std::enable_shared_from_this _thread_pool; std::atomic _max_transaction_time_ms; // modified by app thread, read by net_plugin thread pool std::atomic _received_block{0}; // modified by net_plugin thread pool fc::microseconds _max_irreversible_block_age_us; @@ -624,19 +621,19 @@ class producer_plugin_impl : public std::enable_shared_from_thischain(); auto before = _unapplied_transactions.size(); - _unapplied_transactions.clear_applied(bsp); - chain.get_mutable_subjective_billing().on_block(_log, bsp, fc::time_point::now()); + _unapplied_transactions.clear_applied(block); + chain.get_mutable_subjective_billing().on_block(_log, block, fc::time_point::now()); if (before > 0) { fc_dlog(_log, "Removed applied transactions before: ${before}, after: ${after}", ("before", before)("after", _unapplied_transactions.size())); } } - void on_block_header(const block_state_ptr& bsp) { - if (_producers.contains(bsp->header.producer)) - _producer_watermarks.consider_new_watermark(bsp->header.producer, bsp->block_num, bsp->block->timestamp); + void on_block_header(chain::account_name producer, uint32_t block_num, chain::block_timestamp_type timestamp) { + if (_producers.contains(producer)) + _producer_watermarks.consider_new_watermark(producer, block_num, timestamp); } void on_irreversible_block(const signed_block_ptr& lib) { @@ -666,7 +663,7 @@ class producer_plugin_impl : public std::enable_shared_from_this& block_id, const block_state_ptr& bsp) { + bool on_incoming_block(const signed_block_ptr& block, const std::optional& block_id, const block_state_legacy_ptr& bsp) { auto& chain = chain_plug->chain(); if (in_producing_mode()) { fc_wlog(_log, "dropped incoming block #${num} id: ${id}", ("num", block->block_num())("id", block_id ? (*block_id).str() : "UNKNOWN")); @@ -694,7 +691,7 @@ class producer_plugin_impl : public std::enable_shared_from_this bsf; + std::future bsf; if (!bsp) { bsf = chain.create_block_state_future(id, block); } @@ -711,7 +708,7 @@ class producer_plugin_impl : public std::enable_shared_from_thischain(); const auto max_trx_time_ms = (trx_type == transaction_metadata::trx_type::read_only) ? -1 : _max_transaction_time_ms.load(); fc::microseconds max_trx_cpu_usage = max_trx_time_ms < 0 ? fc::microseconds::maximum() : fc::milliseconds(max_trx_time_ms); - auto future = transaction_metadata::start_recover_keys(trx, - chain.get_thread_pool(), - chain.get_chain_id(), - fc::microseconds(max_trx_cpu_usage), - trx_type, - chain.configured_subjective_signature_length_limit()); - auto is_transient = (trx_type == transaction_metadata::trx_type::read_only || trx_type == transaction_metadata::trx_type::dry_run); if (!is_transient) { next = [this, trx, next{std::move(next)}](const next_function_variant& response) { @@ -826,38 +815,60 @@ class producer_plugin_impl : public std::enable_shared_from_this_time_tracker.add_idle_time(start); - auto trx_tracker = self->_time_tracker.start_trx(is_transient, start); - fc_tlog(_log, "Time since last trx: ${t}us", ("t", idle_time)); - - auto exception_handler = - [self, is_transient, &next, trx{std::move(trx)}, &start](fc::exception_ptr ex) { - self->log_trx_results(trx, nullptr, ex, 0, start, is_transient); - next(std::move(ex)); - }; - try { - auto result = future.get(); - if (!self->process_incoming_transaction_async(result, api_trx, return_failure_traces, trx_tracker, next)) { - if (self->in_producing_mode()) { - self->schedule_maybe_produce_block(true); - } else { - self->restart_speculative_block(); - } - } - } - CATCH_AND_CALL(exception_handler); - }); - } - }); + boost::asio::post( + chain_plug->chain().get_thread_pool(), // use chain thread pool for key recovery + [this, trx{trx}, time_limit{max_trx_cpu_usage}, trx_type, is_transient, next{std::move(next)}, api_trx, return_failure_traces]() mutable { + + chain::controller& chain = chain_plug->chain(); + transaction_metadata_ptr trx_meta; + try { + trx_meta = transaction_metadata::recover_keys(trx, chain.get_chain_id(), time_limit, trx_type, + chain.configured_subjective_signature_length_limit()); + } catch (...) { + // use read_write when read is likely fine; maintains previous behavior of next() always being called from the main thread + app().executor().post( + priority::low, exec_queue::read_write, + [this, ex_ptr{std::current_exception()}, trx{std::move(trx)}, is_transient, next{std::move(next)}]() { + auto start = fc::time_point::now(); + auto idle_time = _time_tracker.add_idle_time(start); + auto trx_tracker = _time_tracker.start_trx(is_transient, start); + fc_tlog(_log, "Time since last trx: ${t}us", ("t", idle_time)); + auto ex_handler = [this, is_transient, &next, &trx](fc::exception_ptr ex) { + log_trx_results(trx, nullptr, ex, 0, is_transient); + next(std::move(ex)); + }; + try { + std::rethrow_exception(ex_ptr); + } CATCH_AND_CALL(ex_handler) + }); + return; + } + + // key recovery complete, continue execution on the main thread + app().executor().post( + priority::low, exec_queue::read_write, + [this, trx_meta{std::move(trx_meta)}, is_transient, next{std::move(next)}, api_trx, return_failure_traces]() { + auto start = fc::time_point::now(); + auto idle_time = _time_tracker.add_idle_time(start); + auto trx_tracker = _time_tracker.start_trx(is_transient, start); + fc_tlog(_log, "Time since last trx: ${t}us", ("t", idle_time)); + + auto exception_handler = [this, is_transient, &next, &trx_meta](fc::exception_ptr ex) { + log_trx_results(trx_meta->packed_trx(), nullptr, ex, 0, is_transient); + next(std::move(ex)); + }; + try { + if (!process_incoming_transaction_async(trx_meta, api_trx, return_failure_traces, trx_tracker, next)) { + if (in_producing_mode()) { + schedule_maybe_produce_block(true); + } else { + restart_speculative_block(); + } + } + } + CATCH_AND_CALL(exception_handler); + }); + }); } bool process_incoming_transaction_async(const transaction_metadata_ptr& trx, @@ -1069,8 +1080,6 @@ void producer_plugin::set_program_options( "Disable subjective CPU billing for P2P transactions") ("disable-subjective-api-billing", bpo::value()->default_value(true), "Disable subjective CPU billing for API transactions") - ("producer-threads", bpo::value()->default_value(my->_thread_pool_size), - "Number of worker threads in producer thread pool") ("snapshots-dir", bpo::value()->default_value("snapshots"), "the location of the snapshots directory (absolute path or relative to application data dir)") ("read-only-threads", bpo::value(), @@ -1188,9 +1197,6 @@ void producer_plugin_impl::plugin_initialize(const boost::program_options::varia ilog("Subjective CPU billing of API trxs disabled "); } - _thread_pool_size = options.at("producer-threads").as(); - EOS_ASSERT(_thread_pool_size > 0, plugin_config_exception, "producer-threads ${num} must be greater than 0", ("num", _thread_pool_size)); - if (options.count("snapshots-dir")) { auto sd = options.at("snapshots-dir").as(); if (sd.is_relative()) { @@ -1268,7 +1274,7 @@ void producer_plugin_impl::plugin_initialize(const boost::program_options::varia ilog("read-only-threads ${s}, max read-only trx time to be enforced: ${t} us", ("s", _ro_thread_pool_size)("t", _ro_max_trx_time_us)); _incoming_block_sync_provider = app().get_method().register_provider( - [this](const signed_block_ptr& block, const std::optional& block_id, const block_state_ptr& bsp) { + [this](const signed_block_ptr& block, const std::optional& block_id, const block_state_legacy_ptr& bsp) { return on_incoming_block(block, block_id, bsp); }); @@ -1318,12 +1324,6 @@ void producer_plugin_impl::plugin_startup() { try { ilog("producer plugin: plugin_startup() begin"); - _thread_pool.start(_thread_pool_size, [](const fc::exception& e) { - fc_elog(_log, "Exception in producer thread pool, exiting: ${e}", ("e", e.to_detail_string())); - app().quit(); - }); - - chain::controller& chain = chain_plug->chain(); EOS_ASSERT(_producers.empty() || chain.get_read_mode() != chain::db_read_mode::IRREVERSIBLE, plugin_config_exception, "node cannot have any producer-name configured because block production is impossible when read_mode is \"irreversible\""); @@ -1334,10 +1334,18 @@ void producer_plugin_impl::plugin_startup() { EOS_ASSERT(_producers.empty() || chain_plug->accept_transactions(), plugin_config_exception, "node cannot have any producer-name configured because no block production is possible with no [api|p2p]-accepted-transactions"); - _accepted_block_connection.emplace(chain.accepted_block.connect([this](const auto& bsp) { on_block(bsp); })); - _accepted_block_header_connection.emplace(chain.accepted_block_header.connect([this](const auto& bsp) { on_block_header(bsp); })); - _irreversible_block_connection.emplace( - chain.irreversible_block.connect([this](const auto& bsp) { on_irreversible_block(bsp->block); })); + _accepted_block_connection.emplace(chain.accepted_block.connect([this](const block_signal_params& t) { + const auto& [ block, id ] = t; + on_block(block); + })); + _accepted_block_header_connection.emplace(chain.accepted_block_header.connect([this](const block_signal_params& t) { + const auto& [ block, id ] = t; + on_block_header(block->producer, block->block_num(), block->timestamp); + })); + _irreversible_block_connection.emplace(chain.irreversible_block.connect([this](const block_signal_params& t) { + const auto& [ block, id ] = t; + on_irreversible_block(block); + })); _block_start_connection.emplace(chain.block_start.connect([this, &chain](uint32_t bs) { try { @@ -1403,7 +1411,6 @@ void producer_plugin_impl::plugin_shutdown() { _ro_timer.cancel(ec); app().executor().stop(); _ro_thread_pool.stop(); - _thread_pool.stop(); _unapplied_transactions.clear(); app().executor().post(0, [me = shared_from_this()]() {}); // keep my pointer alive until queue is drained @@ -2048,22 +2055,20 @@ inline std::string get_detailed_contract_except_info(const packed_transaction_pt } void producer_plugin_impl::log_trx_results(const transaction_metadata_ptr& trx, - const transaction_trace_ptr& trace, - const fc::time_point& start) { + const transaction_trace_ptr& trace) { uint32_t billed_cpu_time_us = (trace && trace->receipt) ? trace->receipt->cpu_usage_us : 0; - log_trx_results(trx->packed_trx(), trace, nullptr, billed_cpu_time_us, start, trx->is_transient()); + log_trx_results(trx->packed_trx(), trace, nullptr, billed_cpu_time_us, trx->is_transient()); } void producer_plugin_impl::log_trx_results(const transaction_metadata_ptr& trx, const fc::exception_ptr& except_ptr) { uint32_t billed_cpu_time_us = trx ? trx->billed_cpu_time_us : 0; - log_trx_results(trx->packed_trx(), nullptr, except_ptr, billed_cpu_time_us, fc::time_point::now(), trx->is_transient()); + log_trx_results(trx->packed_trx(), nullptr, except_ptr, billed_cpu_time_us, trx->is_transient()); } void producer_plugin_impl::log_trx_results(const packed_transaction_ptr& trx, const transaction_trace_ptr& trace, const fc::exception_ptr& except_ptr, uint32_t billed_cpu_us, - const fc::time_point& start, bool is_transient) { chain::controller& chain = chain_plug->chain(); @@ -2231,7 +2236,7 @@ producer_plugin_impl::handle_push_result(const transaction_metadata_ptr& if (!disable_subjective_enforcement) // subjectively bill failure when producing since not in objective cpu account billing subjective_bill.subjective_bill_failure(first_auth, trace->elapsed, fc::time_point::now()); - log_trx_results(trx, trace, start); + log_trx_results(trx, trace); // this failed our configured maximum transaction time, we don't want to replay it fc_tlog(_log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}, except: ${e}", ("c", e.code())("a", first_auth)("p", prev_billed_cpu_time_us)("r", end - start)("id", trx->id())("e", e)); @@ -2250,7 +2255,7 @@ producer_plugin_impl::handle_push_result(const transaction_metadata_ptr& } else { fc_tlog(_log, "Subjective bill for success ${a}: ${b} elapsed ${t}us, time ${r}us", ("a", first_auth)("b", sub_bill)("t", trace->elapsed)("r", end - start)); - log_trx_results(trx, trace, start); + log_trx_results(trx, trace); // if producing then trx is in objective cpu account billing if (!disable_subjective_enforcement && !in_producing_mode()) { subjective_bill.subjective_bill(trx->id(), trx->packed_trx()->expiration(), first_auth, trace->elapsed); @@ -2643,7 +2648,7 @@ void producer_plugin_impl::produce_block() { chain.commit_block(); - block_state_ptr new_bs = chain.head_block_state(); + block_state_legacy_ptr new_bs = chain.head_block_state(); producer_plugin::produced_block_metrics metrics; br.total_time += fc::time_point::now() - start; diff --git a/plugins/producer_plugin/test/test_trx_full.cpp b/plugins/producer_plugin/test/test_trx_full.cpp index b07c1ec8ea..51abbf3a3e 100644 --- a/plugins/producer_plugin/test/test_trx_full.cpp +++ b/plugins/producer_plugin/test/test_trx_full.cpp @@ -68,15 +68,15 @@ auto make_unique_trx( const chain_id_type& chain_id ) { } // verify all trxs are in blocks only once -bool verify_equal( const std::deque& trxs, const std::deque& all_blocks) { +bool verify_equal( const std::deque& trxs, const std::deque& all_blocks) { std::set trxs_ids; // trx can appear more than once if they were aborted std::set blk_trxs_ids; for( const auto& trx : trxs ) { trxs_ids.emplace( trx->id() ); } - for( const auto& bs : all_blocks ) { - for( const auto& trx_receipt : bs->block->transactions ) { + for( const auto& block : all_blocks ) { + for( const auto& trx_receipt : block->transactions ) { const auto& trx = std::get( trx_receipt.trx ).get_transaction(); blk_trxs_ids.emplace( trx.id() ); } @@ -126,13 +126,14 @@ BOOST_AUTO_TEST_CASE(producer) { auto[prod_plug, chain_plug] = plugin_fut.get(); auto chain_id = chain_plug->get_chain_id(); - std::deque all_blocks; + std::deque all_blocks; std::promise empty_blocks_promise; std::future empty_blocks_fut = empty_blocks_promise.get_future(); - auto ab = chain_plug->chain().accepted_block.connect( [&](const block_state_ptr& bsp) { + auto ab = chain_plug->chain().accepted_block.connect( [&](const chain::block_signal_params& t) { + const auto& [ block, id ] = t; static int num_empty = std::numeric_limits::max(); - all_blocks.push_back( bsp ); - if( bsp->block->transactions.empty() ) { + all_blocks.push_back( block ); + if( block->transactions.empty() ) { --num_empty; if( num_empty == 0 ) empty_blocks_promise.set_value(); } else { // we want a few empty blocks after we have some non-empty blocks diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/session.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/session.hpp index 5ff50848a3..94da1e3e1d 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/session.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/session.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include #include #include @@ -26,7 +25,7 @@ struct send_queue_entry_base { struct session_base { virtual void send_update(bool changed) = 0; - virtual void send_update(const eosio::chain::block_state_ptr& block_state) = 0; + virtual void send_update(const chain::signed_block_ptr& block, const chain::block_id_type& id) = 0; virtual ~session_base() = default; std::optional current_request; @@ -35,15 +34,17 @@ struct session_base { class send_update_send_queue_entry : public send_queue_entry_base { std::shared_ptr session; - const chain::block_state_ptr block_state; + const chain::signed_block_ptr block; + const chain::block_id_type id; public: - send_update_send_queue_entry(std::shared_ptr s, chain::block_state_ptr block_state) + send_update_send_queue_entry(std::shared_ptr s, chain::signed_block_ptr block, const chain::block_id_type& id) : session(std::move(s)) - , block_state(std::move(block_state)){} + , block(std::move(block)) + , id(id){} void send_entry() override { - if( block_state ) { - session->send_update(block_state); + if( block) { + session->send_update(block, id); } else { session->send_update(false); } @@ -118,14 +119,14 @@ class session_manager { void send_updates() { for( auto& s : session_set ) { if (s->need_to_send_update ) { - add_send_queue(s, std::make_unique(s, nullptr)); + add_send_queue(s, std::make_unique(s, nullptr, chain::block_id_type{})); } } } - void send_update(const chain::block_state_ptr& block_state) { + void send_update(const chain::signed_block_ptr& block, const chain::block_id_type& id) { for( auto& s : session_set ) { - add_send_queue(s, std::make_unique(s, block_state)); + add_send_queue(s, std::make_unique(s, block, id)); } } @@ -481,7 +482,7 @@ struct session : session_base, std::enable_shared_from_thismax_messages_in_flight) { session_mgr.pop_entry(false); @@ -502,7 +503,7 @@ struct session : session_base, std::enable_shared_from_this block_id = - (block_state && block_state->block_num == to_send_block_num) ? block_state->id : plugin.get_block_id(to_send_block_num); + (block && block->block_num() == to_send_block_num) ? id : plugin.get_block_id(to_send_block_num); if (block_id && position_it && (*position_it)->block_num == to_send_block_num) { // This branch happens when the head block of nodeos is behind the head block of connecting client. @@ -526,8 +527,10 @@ struct session : session_base, std::enable_shared_from_thisfetch_block) - plugin.get_block(to_send_block_num, block_state, result.block); + if (current_request->fetch_block) { + uint32_t block_num = block ? block->block_num() : 0; // block can be nullptr in testing + plugin.get_block(to_send_block_num, block_num, block, result.block); + } if (current_request->fetch_traces && plugin.get_trace_log()) result.traces.emplace(); if (current_request->fetch_deltas && plugin.get_chain_state_log()) @@ -554,23 +557,24 @@ struct session : session_base, std::enable_shared_from_this>(this->shared_from_this(), std::move(result))->send_entry(); } - void send_update(const chain::block_state_ptr& block_state) override { + void send_update(const chain::signed_block_ptr& block, const chain::block_id_type& id) override { if (!current_request || !current_request->max_messages_in_flight) { session_mgr.pop_entry(false); return; } + auto block_num = block->block_num(); state_history::get_blocks_result_v0 result; - result.head = {block_state->block_num, block_state->id}; - to_send_block_num = std::min(block_state->block_num, to_send_block_num); - send_update(std::move(result), block_state); + result.head = {block_num, id}; + to_send_block_num = std::min(block_num, to_send_block_num); + send_update(std::move(result), block, id); } void send_update(bool changed) override { if (changed || need_to_send_update) { state_history::get_blocks_result_v0 result; result.head = plugin.get_block_head(); - send_update(std::move(result), {}); + send_update(std::move(result), nullptr, chain::block_id_type{}); } else { session_mgr.pop_entry(false); } diff --git a/plugins/state_history_plugin/state_history_plugin.cpp b/plugins/state_history_plugin/state_history_plugin.cpp index a779a50be0..c40a695e2f 100644 --- a/plugins/state_history_plugin/state_history_plugin.cpp +++ b/plugins/state_history_plugin/state_history_plugin.cpp @@ -88,11 +88,11 @@ struct state_history_plugin_impl : std::enable_shared_from_thisblock_num) { - p = block_state->block; + if (block_num == block_state_block_num) { + p = block; } else { p = chain_plug->chain().fetch_block_by_number(block_num); } @@ -107,8 +107,8 @@ struct state_history_plugin_impl : std::enable_shared_from_this& result) const { - auto p = get_block(block_num, block_state); + void get_block(uint32_t block_num, uint32_t block_state_block_num, const signed_block_ptr& block, std::optional& result) const { + auto p = get_block(block_num, block_state_block_num, block); if (p) result = fc::raw::pack(*p); } @@ -201,12 +201,12 @@ struct state_history_plugin_impl : std::enable_shared_from_this(*block), block->block_num()); } catch (const fc::exception& e) { fc_elog(_log, "fc::exception: ${details}", ("details", e.to_detail_string())); // Both app().quit() and exception throwing are required. Without app().quit(), @@ -224,8 +224,8 @@ struct state_history_plugin_impl : std::enable_shared_from_thisshared_from_this(), block_state]() { - self->get_session_manager().send_update(block_state); + boost::asio::post(get_ship_executor(), [self = this->shared_from_this(), block, id]() { + self->get_session_manager().send_update(block, id); }); } @@ -243,29 +243,29 @@ struct state_history_plugin_impl : std::enable_shared_from_thisid, + .block_id = id, .payload_size = 0}; - trace_log->pack_and_write_entry(header, block_state->block->previous, [this, &block_state](auto&& buf) { - trace_converter.pack(buf, trace_debug_mode, block_state); + trace_log->pack_and_write_entry(header, block->previous, [this, &block](auto&& buf) { + trace_converter.pack(buf, trace_debug_mode, block); }); } // called from main thread - void store_chain_state(const block_state_ptr& block_state) { + void store_chain_state(const block_id_type& id, const signed_block_header& block_header, uint32_t block_num) { if (!chain_state_log) return; bool fresh = chain_state_log->empty(); if (fresh) - fc_ilog(_log, "Placing initial state in block ${n}", ("n", block_state->block_num)); + fc_ilog(_log, "Placing initial state in block ${n}", ("n", block_num)); state_history_log_header header{ - .magic = ship_magic(ship_current_version, 0), .block_id = block_state->id, .payload_size = 0}; - chain_state_log->pack_and_write_entry(header, block_state->header.previous, [this, fresh](auto&& buf) { + .magic = ship_magic(ship_current_version, 0), .block_id = id, .payload_size = 0}; + chain_state_log->pack_and_write_entry(header, block_header.previous, [this, fresh](auto&& buf) { pack_deltas(buf, chain_plug->chain().db(), fresh); }); } // store_chain_state @@ -329,7 +329,10 @@ void state_history_plugin_impl::plugin_initialize(const variables_map& options) on_applied_transaction(std::get<0>(t), std::get<1>(t)); })); accepted_block_connection.emplace( - chain.accepted_block.connect([&](const block_state_ptr& p) { on_accepted_block(p); })); + chain.accepted_block.connect([&](const block_signal_params& t) { + const auto& [ block, id ] = t; + on_accepted_block(block, id); + })); block_start_connection.emplace( chain.block_start.connect([&](uint32_t block_num) { on_block_start(block_num); })); @@ -406,7 +409,7 @@ void state_history_plugin_impl::plugin_startup() { auto bsp = chain.head_block_state(); if( bsp && chain_state_log && chain_state_log->empty() ) { fc_ilog( _log, "Storing initial state on startup, this can take a considerable amount of time" ); - store_chain_state( bsp ); + store_chain_state( bsp->id, bsp->header, bsp->block_num ); fc_ilog( _log, "Done storing initial state on startup" ); } first_available_block = chain.earliest_available_block_num(); diff --git a/plugins/state_history_plugin/tests/session_test.cpp b/plugins/state_history_plugin/tests/session_test.cpp index e1bc439ef2..bcfb2a219d 100644 --- a/plugins/state_history_plugin/tests/session_test.cpp +++ b/plugins/state_history_plugin/tests/session_test.cpp @@ -123,7 +123,7 @@ struct mock_state_history_plugin { fc::logger& get_logger() { return logger; } - void get_block(uint32_t block_num, const eosio::chain::block_state_ptr& block_state, + void get_block(uint32_t block_num, uint32_t block_state_block_num, const eosio::chain::signed_block_ptr& block, std::optional& result) const { result.emplace().resize(16); } diff --git a/plugins/test_control_plugin/test_control_plugin.cpp b/plugins/test_control_plugin/test_control_plugin.cpp index 1f7192dc04..2bf43bdb55 100644 --- a/plugins/test_control_plugin/test_control_plugin.cpp +++ b/plugins/test_control_plugin/test_control_plugin.cpp @@ -15,9 +15,9 @@ class test_control_plugin_impl { void kill_on_head(account_name prod, uint32_t where_in_seq); private: - void accepted_block(const chain::block_state_ptr& bsp); - void applied_irreversible_block(const chain::block_state_ptr& bsp); - void process_next_block_state(const chain::block_state_ptr& bsp); + void accepted_block(const chain::block_id_type& id); + void applied_irreversible_block(const chain::block_id_type& id); + void process_next_block_state(const chain::block_id_type& id); std::optional _accepted_block_connection; std::optional _irreversible_block_connection; @@ -32,12 +32,14 @@ class test_control_plugin_impl { void test_control_plugin_impl::connect() { _irreversible_block_connection.emplace( - _chain.irreversible_block.connect( [&]( const chain::block_state_ptr& bs ) { - applied_irreversible_block( bs ); + _chain.irreversible_block.connect( [&]( const chain::block_signal_params& t ) { + const auto& [ block, id ] = t; + applied_irreversible_block( id ); } )); _accepted_block_connection = - _chain.accepted_block.connect( [&]( const chain::block_state_ptr& bs ) { - accepted_block( bs ); + _chain.accepted_block.connect( [&]( const chain::block_signal_params& t ) { + const auto& [ block, id ] = t; + accepted_block( id ); } ); } @@ -46,19 +48,21 @@ void test_control_plugin_impl::disconnect() { _irreversible_block_connection.reset(); } -void test_control_plugin_impl::applied_irreversible_block(const chain::block_state_ptr& bsp) { +void test_control_plugin_impl::applied_irreversible_block(const chain::block_id_type& id) { if (_track_lib) - process_next_block_state(bsp); + process_next_block_state(id); } -void test_control_plugin_impl::accepted_block(const chain::block_state_ptr& bsp) { +void test_control_plugin_impl::accepted_block(const chain::block_id_type& id) { if (_track_head) - process_next_block_state(bsp); + process_next_block_state(id); } -void test_control_plugin_impl::process_next_block_state(const chain::block_state_ptr& bsp) { +void test_control_plugin_impl::process_next_block_state(const chain::block_id_type& id) { // Tests expect the shutdown only after signaling a producer shutdown and seeing a full production cycle const auto block_time = _chain.head_block_time() + fc::microseconds(chain::config::block_interval_us); + // have to fetch bsp due to get_scheduled_producer call + const auto& bsp = _chain.fetch_block_state_by_id(id); const auto& producer_authority = bsp->get_scheduled_producer(block_time); const auto producer_name = producer_authority.producer_name; const auto slot = bsp->block->timestamp.slot % chain::config::producer_repetitions; diff --git a/plugins/trace_api_plugin/include/eosio/trace_api/chain_extraction.hpp b/plugins/trace_api_plugin/include/eosio/trace_api/chain_extraction.hpp index cb56ddca00..05860bb1ef 100644 --- a/plugins/trace_api_plugin/include/eosio/trace_api/chain_extraction.hpp +++ b/plugins/trace_api_plugin/include/eosio/trace_api/chain_extraction.hpp @@ -31,13 +31,13 @@ class chain_extraction_impl_type { } /// connect to chain controller accepted_block signal - void signal_accepted_block( const chain::block_state_ptr& bsp ) { - on_accepted_block( bsp ); + void signal_accepted_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { + on_accepted_block( block, id ); } /// connect to chain controller irreversible_block signal - void signal_irreversible_block( const chain::block_state_ptr& bsp ) { - on_irreversible_block( bsp ); + void signal_irreversible_block( uint32_t block_num ) { + on_irreversible_block( block_num ); } /// connect to chain controller block_start signal @@ -63,12 +63,12 @@ class chain_extraction_impl_type { } } - void on_accepted_block(const chain::block_state_ptr& block_state) { - store_block_trace( block_state ); + void on_accepted_block(const chain::signed_block_ptr& block, const chain::block_id_type& id ) { + store_block_trace( block, id ); } - void on_irreversible_block( const chain::block_state_ptr& block_state ) { - store_lib( block_state ); + void on_irreversible_block( uint32_t block_num ) { + store_lib( block_num ); } void on_block_start( uint32_t block_num ) { @@ -80,18 +80,18 @@ class chain_extraction_impl_type { onblock_trace.reset(); } - void store_block_trace( const chain::block_state_ptr& block_state ) { + void store_block_trace( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { try { using transaction_trace_t = transaction_trace_v3; - auto bt = create_block_trace( block_state ); + auto bt = create_block_trace( block, id ); std::vector traces; - traces.reserve( block_state->block->transactions.size() + 1 ); + traces.reserve( block->transactions.size() + 1 ); block_trxs_entry tt; - tt.ids.reserve(block_state->block->transactions.size() + 1); + tt.ids.reserve(block->transactions.size() + 1); if( onblock_trace ) traces.emplace_back( to_transaction_trace( *onblock_trace )); - for( const auto& r : block_state->block->transactions ) { + for( const auto& r : block->transactions ) { transaction_id_type id; if( std::holds_alternative(r.trx)) { id = std::get(r.trx); @@ -117,9 +117,9 @@ class chain_extraction_impl_type { } } - void store_lib( const chain::block_state_ptr& bsp ) { + void store_lib( uint32_t block_num ) { try { - store.append_lib( bsp->block_num ); + store.append_lib( block_num ); } catch( ... ) { except_handler( MAKE_EXCEPTION_WITH_CONTEXT( std::current_exception() ) ); } diff --git a/plugins/trace_api_plugin/include/eosio/trace_api/extract_util.hpp b/plugins/trace_api_plugin/include/eosio/trace_api/extract_util.hpp index cec44ab10b..ce240a9b5e 100644 --- a/plugins/trace_api_plugin/include/eosio/trace_api/extract_util.hpp +++ b/plugins/trace_api_plugin/include/eosio/trace_api/extract_util.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include namespace eosio { namespace trace_api { @@ -63,16 +62,16 @@ inline TransactionTrace to_transaction_trace( const cache_trace& t ) { return r; } -inline block_trace_v2 create_block_trace( const chain::block_state_ptr& bsp ) { +inline block_trace_v2 create_block_trace( const chain::signed_block_ptr& block, const chain::block_id_type& id ) { block_trace_v2 r; - r.id = bsp->id; - r.number = bsp->block_num; - r.previous_id = bsp->block->previous; - r.timestamp = bsp->block->timestamp; - r.producer = bsp->block->producer; - r.schedule_version = bsp->block->schedule_version; - r.transaction_mroot = bsp->block->transaction_mroot; - r.action_mroot = bsp->block->action_mroot; + r.id = id; + r.number = block->block_num(); + r.previous_id = block->previous; + r.timestamp = block->timestamp; + r.producer = block->producer; + r.schedule_version = block->schedule_version; + r.transaction_mroot = block->transaction_mroot; + r.action_mroot = block->action_mroot; return r; } diff --git a/plugins/trace_api_plugin/include/eosio/trace_api/store_provider.hpp b/plugins/trace_api_plugin/include/eosio/trace_api/store_provider.hpp index d30d5f9a21..cb0f60f386 100644 --- a/plugins/trace_api_plugin/include/eosio/trace_api/store_provider.hpp +++ b/plugins/trace_api_plugin/include/eosio/trace_api/store_provider.hpp @@ -66,7 +66,6 @@ namespace eosio::trace_api { const auto offset = file.tellp(); file.write(data.data(), data.size()); file.flush(); - file.sync(); return offset; } diff --git a/plugins/trace_api_plugin/test/include/eosio/trace_api/test_common.hpp b/plugins/trace_api_plugin/test/include/eosio/trace_api/test_common.hpp index 7208683bd2..a38b034036 100644 --- a/plugins/trace_api_plugin/test/include/eosio/trace_api/test_common.hpp +++ b/plugins/trace_api_plugin/test/include/eosio/trace_api/test_common.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -71,7 +71,7 @@ namespace eosio::trace_api { auto priv_key = get_private_key( block->producer, "active" ); auto pub_key = get_public_key( block->producer, "active" ); - auto prev = std::make_shared(); + auto prev = std::make_shared(); auto header_bmroot = chain::digest_type::hash( std::make_pair( block->digest(), prev->blockroot_merkle.get_root())); auto sig_digest = chain::digest_type::hash( std::make_pair( header_bmroot, prev->pending_schedule.schedule_hash )); block->producer_signature = priv_key.sign( sig_digest ); @@ -85,14 +85,14 @@ namespace eosio::trace_api { result.emplace_back( k.sign( d )); return result; }; - chain::pending_block_header_state pbhs; + chain::pending_block_header_state_legacy pbhs; pbhs.producer = block->producer; pbhs.timestamp = block->timestamp; chain::producer_authority_schedule schedule = {0, {chain::producer_authority{block->producer, chain::block_signing_authority_v0{1, {{pub_key, 1}}}}}}; pbhs.active_schedule = schedule; pbhs.valid_block_signing_authority = chain::block_signing_authority_v0{1, {{pub_key, 1}}}; - auto bsp = std::make_shared( + auto bsp = std::make_shared( std::move( pbhs ), std::move( block ), eosio::chain::deque(), diff --git a/plugins/trace_api_plugin/test/test_extraction.cpp b/plugins/trace_api_plugin/test/test_extraction.cpp index 3403ef1dc5..e053ce6c52 100644 --- a/plugins/trace_api_plugin/test/test_extraction.cpp +++ b/plugins/trace_api_plugin/test/test_extraction.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include @@ -136,8 +136,8 @@ struct extraction_test_fixture { extraction_impl.signal_applied_transaction(trace, ptrx); } - void signal_accepted_block( const chain::block_state_ptr& bsp ) { - extraction_impl.signal_accepted_block(bsp); + void signal_accepted_block( const chain::block_state_legacy_ptr& bsp ) { + extraction_impl.signal_accepted_block(bsp->block, bsp->id); } // fixture data and methods diff --git a/plugins/trace_api_plugin/trace_api_plugin.cpp b/plugins/trace_api_plugin/trace_api_plugin.cpp index 8a412f8b27..8aa7ea9556 100644 --- a/plugins/trace_api_plugin/trace_api_plugin.cpp +++ b/plugins/trace_api_plugin/trace_api_plugin.cpp @@ -377,16 +377,18 @@ struct trace_api_plugin_impl { })); accepted_block_connection.emplace( - chain.accepted_block.connect([this](const chain::block_state_ptr& p) { + chain.accepted_block.connect([this](const chain::block_signal_params& t) { emit_killer([&](){ - extraction->signal_accepted_block(p); + const auto& [ block, id ] = t; + extraction->signal_accepted_block(block, id); }); })); irreversible_block_connection.emplace( - chain.irreversible_block.connect([this](const chain::block_state_ptr& p) { + chain.irreversible_block.connect([this](const chain::block_signal_params& t) { + const auto& [ block, id ] = t; emit_killer([&](){ - extraction->signal_irreversible_block(p); + extraction->signal_irreversible_block(block->block_num()); }); })); diff --git a/programs/leap-util/actions/chain.cpp b/programs/leap-util/actions/chain.cpp index 9a12a3b21c..25e71e38ec 100644 --- a/programs/leap-util/actions/chain.cpp +++ b/programs/leap-util/actions/chain.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -19,15 +19,6 @@ using namespace eosio; using namespace eosio::chain; - -// reflect chainbase::environment for --print-build-info option -FC_REFLECT_ENUM(chainbase::environment::os_t, - (OS_LINUX) (OS_MACOS) (OS_WINDOWS) (OS_OTHER)) -FC_REFLECT_ENUM(chainbase::environment::arch_t, - (ARCH_X86_64) (ARCH_ARM) (ARCH_RISCV) (ARCH_OTHER)) -FC_REFLECT(chainbase::environment, (debug) (os) (arch) (boost_version) (compiler)) - - void chain_actions::setup(CLI::App& app) { auto* sub = app.add_subcommand("chain-state", "chain utility"); sub->add_option("--state-dir", opt->sstate_state_dir, "The location of the state directory (absolute path or relative to the current directory)")->capture_default_str(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5234244df3..12cfc0821f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,6 +16,7 @@ target_include_directories( plugin_test PUBLIC configure_file(${CMAKE_CURRENT_SOURCE_DIR}/p2p_tests/dawn_515/test.sh ${CMAKE_CURRENT_BINARY_DIR}/p2p_tests/dawn_515/test.sh COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/block_log_util_test.py ${CMAKE_CURRENT_BINARY_DIR}/block_log_util_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/block_log_retain_blocks_test.py ${CMAKE_CURRENT_BINARY_DIR}/block_log_retain_blocks_test.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bridge_for_fork_test_shape.json ${CMAKE_CURRENT_BINARY_DIR}/bridge_for_fork_test_shape.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cluster_launcher.py ${CMAKE_CURRENT_BINARY_DIR}/cluster_launcher.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/distributed-transactions-test.py ${CMAKE_CURRENT_BINARY_DIR}/distributed-transactions-test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sample-cluster-map.json ${CMAKE_CURRENT_BINARY_DIR}/sample-cluster-map.json COPYONLY) @@ -46,7 +47,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_producer_watermark_test.py ${C configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cli_test.py ${CMAKE_CURRENT_BINARY_DIR}/cli_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ship_test.py ${CMAKE_CURRENT_BINARY_DIR}/ship_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ship_streamer_test.py ${CMAKE_CURRENT_BINARY_DIR}/ship_streamer_test.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/large-lib-test.py ${CMAKE_CURRENT_BINARY_DIR}/large-lib-test.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/lib_advance_test.py ${CMAKE_CURRENT_BINARY_DIR}/lib_advance_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/http_plugin_test.py ${CMAKE_CURRENT_BINARY_DIR}/http_plugin_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/p2p_high_latency_test.py ${CMAKE_CURRENT_BINARY_DIR}/p2p_high_latency_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/p2p_multiple_listen_test.py ${CMAKE_CURRENT_BINARY_DIR}/p2p_multiple_listen_test.py COPYONLY) @@ -67,7 +68,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resource_monitor_plugin_test.py ${CMA configure_file(${CMAKE_CURRENT_SOURCE_DIR}/light_validation_sync_test.py ${CMAKE_CURRENT_BINARY_DIR}/light_validation_sync_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/trace_plugin_test.py ${CMAKE_CURRENT_BINARY_DIR}/trace_plugin_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nested_container_multi_index_test.py ${CMAKE_CURRENT_BINARY_DIR}/nested_container_multi_index_test.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/large-lib-test.py ${CMAKE_CURRENT_BINARY_DIR}/large-lib-test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/auto_bp_peering_test.py ${CMAKE_CURRENT_BINARY_DIR}/auto_bp_peering_test.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/auto_bp_peering_test_shape.json ${CMAKE_CURRENT_BINARY_DIR}/auto_bp_peering_test_shape.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gelf_test.py ${CMAKE_CURRENT_BINARY_DIR}/gelf_test.py COPYONLY) @@ -80,6 +80,11 @@ else() set(UNSHARE "") endif() +option(LEAP_ENABLE_RELEASE_BUILD_TEST "Enables a test that verifies nodeos was compiled with compiler options typical for a release build" On) +if(LEAP_ENABLE_RELEASE_BUILD_TEST) + add_test(NAME release-build-test COMMAND tests/release-build.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + #To run plugin_test with all log from blockchain displayed, put --verbose after --, i.e. plugin_test -- --verbose add_test(NAME plugin_test COMMAND plugin_test --report_level=detailed --color_output) @@ -179,7 +184,6 @@ set_property(TEST trx_finality_status_forked_test PROPERTY LABELS nonparalleliza add_test(NAME db_modes_test COMMAND tests/db_modes_test.sh -v WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_tests_properties(db_modes_test PROPERTIES COST 6000) -add_test(NAME release-build-test COMMAND tests/release-build.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME version-label-test COMMAND tests/version-label.sh "v${VERSION_FULL}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME full-version-label-test COMMAND tests/full-version-label.sh "v${VERSION_FULL}" ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME nested_container_multi_index_test COMMAND tests/nested_container_multi_index_test.py -n 2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -241,8 +245,8 @@ set_property(TEST nodeos_retry_transaction_lr_test PROPERTY LABELS long_running_ add_test(NAME cli_test COMMAND tests/cli_test.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST cli_test PROPERTY LABELS nonparallelizable_tests) -add_test(NAME larger_lib_test COMMAND tests/large-lib-test.py ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -set_property(TEST larger_lib_test PROPERTY LABELS nonparallelizable_tests) +add_test(NAME lib_advance_test COMMAND tests/lib_advance_test.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +set_property(TEST lib_advance_test PROPERTY LABELS nonparallelizable_tests) add_test(NAME http_plugin_test COMMAND tests/http_plugin_test.py ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_tests_properties(http_plugin_test PROPERTIES TIMEOUT 100) diff --git a/tests/PerformanceHarness/README.md b/tests/PerformanceHarness/README.md index 42ff944ef0..0b54191863 100644 --- a/tests/PerformanceHarness/README.md +++ b/tests/PerformanceHarness/README.md @@ -371,7 +371,6 @@ Operational Modes: ``` usage: PerformanceHarnessScenarioRunner.py findMax testBpOpMode [--skip-tps-test] - [--calc-producer-threads {none,lmax,full}] [--calc-chain-threads {none,lmax,full}] [--calc-net-threads {none,lmax,full}] [--del-test-report] @@ -398,22 +397,6 @@ Performance Harness: --skip-tps-test Determines whether to skip the max TPS measurement tests - --calc-producer-threads {none,lmax,full} - Determines whether to calculate number of worker - threads to use in producer thread pool ("none", - "lmax", or "full"). In "none" mode, the default, no - calculation will be attempted and the configured - --producer-threads value will be used. In "lmax" mode, - producer threads will incrementally be tested, - starting at plugin default, until the performance rate - ceases to increase with the addition of additional - threads. In "full" mode producer threads will - incrementally be tested from plugin default..num - logical processors, recording each performance and - choosing the local max performance (same value as - would be discovered in "lmax" mode). Useful for - graphing the full performance impact of each available - thread. --calc-chain-threads {none,lmax,full} Determines whether to calculate number of worker threads to use in chain thread pool ("none", "lmax", @@ -505,7 +488,6 @@ usage: PerformanceHarnessScenarioRunner.py findMax testBpOpMode overrideBasicTes [--net-threads NET_THREADS] [--disable-subjective-billing DISABLE_SUBJECTIVE_BILLING] [--produce-block-offset-ms PRODUCE_BLOCK_OFFSET_MS] - [--producer-threads PRODUCER_THREADS] [--read-only-write-window-time-us READ_ONLY_WRITE_WINDOW_TIME_US] [--read-only-read-window-time-us READ_ONLY_READ_WINDOW_TIME_US] [--http-max-in-flight-requests HTTP_MAX_IN_FLIGHT_REQUESTS] @@ -582,8 +564,6 @@ Performance Test Basic Base: --produce-block-offset-ms PRODUCE_BLOCK_OFFSET_MS The number of milliseconds early the last block of a production round should be produced. - --producer-threads PRODUCER_THREADS - Number of worker threads in producer thread pool --read-only-write-window-time-us READ_ONLY_WRITE_WINDOW_TIME_US Time in microseconds the write window lasts. --read-only-read-window-time-us READ_ONLY_READ_WINDOW_TIME_US @@ -665,7 +645,6 @@ The following classes and scripts are typically used by the Performance Harness [--net-threads NET_THREADS] [--disable-subjective-billing DISABLE_SUBJECTIVE_BILLING] [--produce-block-offset-ms PRODUCE_BLOCK_OFFSET_MS] - [--producer-threads PRODUCER_THREADS] [--http-max-in-flight-requests HTTP_MAX_IN_FLIGHT_REQUESTS] [--http-max-response-time-ms HTTP_MAX_RESPONSE_TIME_MS] [--http-max-bytes-in-flight-mb HTTP_MAX_BYTES_IN_FLIGHT_MB] @@ -746,8 +725,6 @@ Performance Test Basic Base: --produce-block-offset-ms PRODUCE_BLOCK_OFFSET_MS The number of milliseconds early the last block of a production round should be produced. - --producer-threads PRODUCER_THREADS - Number of worker threads in producer thread pool (default: 2) --http-max-in-flight-requests HTTP_MAX_IN_FLIGHT_REQUESTS Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded. -1 for unlimited (default: -1) --http-max-response-time-ms HTTP_MAX_RESPONSE_TIME_MS @@ -879,7 +856,7 @@ The Performance Harness Scenario Runner, through the `PerformanceTest` and `Perf Command used to run test and generate report: ``` bash -./tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-producer-threads lmax --calc-chain-threads lmax --calc-net-threads lmax +./tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-chain-threads lmax --calc-net-threads lmax ``` ### Report Breakdown @@ -1255,7 +1232,7 @@ Finally, the full detail test report for each of the determined max TPS throughp "analysisFinish": "2023-08-18T17:39:08.002767" }, "args": { - "rawCmdLine ": "tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-producer-threads lmax --calc-chain-threads lmax --calc-net-threads lmax", + "rawCmdLine ": "tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-chain-threads lmax --calc-net-threads lmax", "dumpErrorDetails": false, "delay": 1, "nodesFile": null, @@ -1621,9 +1598,6 @@ Finally, the full detail test report for each of the determined max TPS throughp "disableSubjectiveApiBilling": true, "_disableSubjectiveApiBillingNodeosDefault": 1, "_disableSubjectiveApiBillingNodeosArg": "--disable-subjective-api-billing", - "producerThreads": 2, - "_producerThreadsNodeosDefault": 2, - "_producerThreadsNodeosArg": "--producer-threads", "snapshotsDir": null, "_snapshotsDirNodeosDefault": "\"snapshots\"", "_snapshotsDirNodeosArg": "--snapshots-dir", @@ -1771,7 +1745,6 @@ Finally, the full detail test report for each of the determined max TPS throughp "quiet": false, "logDirRoot": ".", "skipTpsTests": false, - "calcProducerThreads": "lmax", "calcChainThreads": "lmax", "calcNetThreads": "lmax", "userTrxDataFile": null, @@ -1915,7 +1888,7 @@ The Performance Test Basic generates, by default, a report that details results } }, "args": { - "rawCmdLine ": "tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-producer-threads lmax --calc-chain-threads lmax --calc-net-threads lmax", + "rawCmdLine ": "tests/PerformanceHarnessScenarioRunner.py findMax testBpOpMode --test-iteration-duration-sec 10 --final-iterations-duration-sec 30 --calc-chain-threads lmax --calc-net-threads lmax", "dumpErrorDetails": false, "delay": 1, "nodesFile": null, @@ -2281,9 +2254,6 @@ The Performance Test Basic generates, by default, a report that details results "disableSubjectiveApiBilling": true, "_disableSubjectiveApiBillingNodeosDefault": 1, "_disableSubjectiveApiBillingNodeosArg": "--disable-subjective-api-billing", - "producerThreads": 2, - "_producerThreadsNodeosDefault": 2, - "_producerThreadsNodeosArg": "--producer-threads", "snapshotsDir": null, "_snapshotsDirNodeosDefault": "\"snapshots\"", "_snapshotsDirNodeosArg": "--snapshots-dir", diff --git a/tests/PerformanceHarness/performance_test.py b/tests/PerformanceHarness/performance_test.py index 489521164e..63f05e2bab 100755 --- a/tests/PerformanceHarness/performance_test.py +++ b/tests/PerformanceHarness/performance_test.py @@ -43,7 +43,6 @@ class PtConfig: quiet: bool=False logDirRoot: Path=Path(".") skipTpsTests: bool=False - calcProducerThreads: str="none" calcChainThreads: str="none" calcNetThreads: str="none" userTrxDataFile: Path=None @@ -368,18 +367,6 @@ def runTest(self): self.testDirsCleanup() self.testDirsSetup() - prodResults = None - if self.ptConfig.calcProducerThreads != "none": - print(f"Performing Producer Thread Optimization Tests") - if self.ptConfig.calcProducerThreads == "full": - optType = PerformanceTest.PluginThreadOptRunType.FULL - else: - optType = PerformanceTest.PluginThreadOptRunType.LOCAL_MAX - prodResults = self.optimizePluginThreadCount(optPlugin=PerformanceTest.PluginThreadOpt.PRODUCER, optType=optType, - minThreadCount=self.clusterConfig.extraNodeosArgs.producerPluginArgs._producerThreadsNodeosDefault) - print(f"Producer Thread Optimization results: {prodResults}") - self.clusterConfig.extraNodeosArgs.producerPluginArgs.threads = prodResults.recommendedThreadCount - chainResults = None if self.ptConfig.calcChainThreads != "none": print(f"Performing Chain Thread Optimization Tests") @@ -413,7 +400,7 @@ def runTest(self): self.testsFinish = datetime.utcnow() - self.report = self.createReport(producerThreadResult=prodResults, chainThreadResult=chainResults, netThreadResult=netResults, tpsTestResult=tpsTestResult, nodeosVers=self.clusterConfig.nodeosVers) + self.report = self.createReport(chainThreadResult=chainResults, netThreadResult=netResults, tpsTestResult=tpsTestResult, nodeosVers=self.clusterConfig.nodeosVers) jsonReport = JsonReportHandler.reportAsJSON(self.report) if not self.ptConfig.quiet: @@ -439,12 +426,6 @@ def createPtParser(suppressHelp:bool=False): ptGrpDescription="Performance Harness testing configuration items." ptParserGroup = ptParser.add_argument_group(title=None if suppressHelp else ptGrpTitle, description=None if suppressHelp else ptGrpDescription) ptParserGroup.add_argument("--skip-tps-test", help=argparse.SUPPRESS if suppressHelp else "Determines whether to skip the max TPS measurement tests", action='store_true') - ptParserGroup.add_argument("--calc-producer-threads", type=str, help=argparse.SUPPRESS if suppressHelp else "Determines whether to calculate number of worker threads to use in producer thread pool (\"none\", \"lmax\", or \"full\"). \ - In \"none\" mode, the default, no calculation will be attempted and the configured --producer-threads value will be used. \ - In \"lmax\" mode, producer threads will incrementally be tested, starting at plugin default, until the performance rate ceases to increase with the addition of additional threads. \ - In \"full\" mode producer threads will incrementally be tested from plugin default..num logical processors, recording each performance and choosing the local max performance (same value as would be discovered in \"lmax\" mode). \ - Useful for graphing the full performance impact of each available thread.", - choices=["none", "lmax", "full"], default="none") ptParserGroup.add_argument("--calc-chain-threads", type=str, help=argparse.SUPPRESS if suppressHelp else "Determines whether to calculate number of worker threads to use in chain thread pool (\"none\", \"lmax\", or \"full\"). \ In \"none\" mode, the default, no calculation will be attempted and the configured --chain-threads value will be used. \ In \"lmax\" mode, producer threads will incrementally be tested, starting at plugin default, until the performance rate ceases to increase with the addition of additional threads. \ diff --git a/tests/PerformanceHarness/performance_test_basic.py b/tests/PerformanceHarness/performance_test_basic.py index a96f24ea83..6ff6345b5f 100755 --- a/tests/PerformanceHarness/performance_test_basic.py +++ b/tests/PerformanceHarness/performance_test_basic.py @@ -664,7 +664,7 @@ def setupClusterConfig(args) -> ClusterConfig: producerPluginArgs = ProducerPluginArgs(disableSubjectiveApiBilling=args.disable_subjective_billing, disableSubjectiveP2pBilling=args.disable_subjective_billing, produceBlockOffsetMs=args.produce_block_offset_ms, - producerThreads=args.producer_threads, maxTransactionTime=-1, + maxTransactionTime=-1, readOnlyWriteWindowTimeUs=args.read_only_write_window_time_us, readOnlyReadWindowTimeUs=args.read_only_read_window_time_us) httpPluginArgs = HttpPluginArgs(httpMaxBytesInFlightMb=args.http_max_bytes_in_flight_mb, httpMaxInFlightRequests=args.http_max_in_flight_requests, @@ -721,7 +721,6 @@ def _createBaseArgumentParser(defEndpointApiDef: str, defProdNodeCnt: int, defVa ptbBaseParserGroup.add_argument("--net-threads", type=int, help=argparse.SUPPRESS if suppressHelp else "Number of worker threads in net_plugin thread pool", default=4) ptbBaseParserGroup.add_argument("--disable-subjective-billing", type=bool, help=argparse.SUPPRESS if suppressHelp else "Disable subjective CPU billing for API/P2P transactions", default=True) ptbBaseParserGroup.add_argument("--produce-block-offset-ms", type=int, help=argparse.SUPPRESS if suppressHelp else "The minimum time to reserve at the end of a production round for blocks to propagate to the next block producer.", default=0) - ptbBaseParserGroup.add_argument("--producer-threads", type=int, help=argparse.SUPPRESS if suppressHelp else "Number of worker threads in producer thread pool", default=2) ptbBaseParserGroup.add_argument("--read-only-write-window-time-us", type=int, help=argparse.SUPPRESS if suppressHelp else "Time in microseconds the write window lasts.", default=200000) ptbBaseParserGroup.add_argument("--read-only-read-window-time-us", type=int, help=argparse.SUPPRESS if suppressHelp else "Time in microseconds the read window lasts.", default=60000) ptbBaseParserGroup.add_argument("--http-max-in-flight-requests", type=int, help=argparse.SUPPRESS if suppressHelp else "Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded. -1 for unlimited", default=-1) diff --git a/tests/PerformanceHarnessScenarioRunner.py b/tests/PerformanceHarnessScenarioRunner.py index a172c5e3a3..51d6123df5 100755 --- a/tests/PerformanceHarnessScenarioRunner.py +++ b/tests/PerformanceHarnessScenarioRunner.py @@ -82,7 +82,6 @@ def main(): quiet=args.quiet, logDirRoot=Path("."), skipTpsTests=args.skip_tps_test, - calcProducerThreads=args.calc_producer_threads, calcChainThreads=args.calc_chain_threads, calcNetThreads=args.calc_net_threads, userTrxDataFile=Path(args.user_trx_data_file) if args.user_trx_data_file is not None else None, diff --git a/tests/TestHarness/Cluster.py b/tests/TestHarness/Cluster.py index cc954ba36a..87ab5eab23 100644 --- a/tests/TestHarness/Cluster.py +++ b/tests/TestHarness/Cluster.py @@ -1,4 +1,3 @@ -import atexit import copy import subprocess import time @@ -76,7 +75,6 @@ def __init__(self, localCluster=True, host="localhost", port=8888, walletHost="l keepRunning: [True|False] If true, leave nodes running when Cluster is destroyed. Implies keepLogs. keepLogs: [True|False] If true, retain log files after cluster shuts down. """ - atexit.register(self.shutdown) self.accounts=[] self.nodes=[] self.unstartedNodes=[] diff --git a/tests/TestHarness/TestHelper.py b/tests/TestHarness/TestHelper.py index 6f3a1244ae..66bebd7cd4 100644 --- a/tests/TestHarness/TestHelper.py +++ b/tests/TestHarness/TestHelper.py @@ -184,3 +184,5 @@ def reportProductionAnalysis(thresholdMs): cluster.testFailed = not testSuccessful if walletMgr: walletMgr.testFailed = not testSuccessful + + cluster.shutdown() diff --git a/tests/abieos b/tests/abieos index 7e77b20a39..ae6854ea7b 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit 7e77b20a3927a41695f7ae969b736bdb4a8e0a74 +Subproject commit ae6854ea7bad22f3dc4554a60124319af7e6cd30 diff --git a/tests/bridge_for_fork_test_shape.json b/tests/bridge_for_fork_test_shape.json new file mode 100644 index 0000000000..7b87e4102f --- /dev/null +++ b/tests/bridge_for_fork_test_shape.json @@ -0,0 +1,114 @@ +{ + "name": "testnet_", + "ssh_helper": { + "ssh_cmd": "/usr/bin/ssh", + "scp_cmd": "/usr/bin/scp", + "ssh_identity": "", + "ssh_args": "" + }, + "nodes": { + "bios":{ + "name": "bios", + "keys": [ + { + "privkey":"5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3", + "pubkey":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" + } + ], + "peers": [], + "producers": [ + "eosio" + ], + "dont_start": false + }, + "testnet_00":{ + "name": "testnet_00", + "keys": [ + { + "privkey":"5Jf4sTk7vwX1MYpLJ2eQFanVvKYXFqGBrCyANPukuP2BJ5WAAKZ", + "pubkey":"EOS58B33q9S7oNkgeFfcoW3VJYu4obfDiqn5RHGE2ige6jVjUhymR" + } + ], + "peers": [ + "bios", + "testnet_01", + "testnet_02", + "testnet_04" + ], + "producers": [ + "defproducera" + ], + "dont_start": false + }, + "testnet_01":{ + "name": "testnet_01", + "keys": [ + { + "privkey":"5HviUPkTEtvF2B1nm8aZUnjma2TzgpKRjuXjwHyy3FME4xDbkZF", + "pubkey":"EOS5CbcTDgbks2ptTxvyCbT9HFbzX7PDHUY2wN4DDnVBhhQr2ZNDE" + } + ], + "peers": [ + "bios", + "testnet_00", + "testnet_02", + "testnet_04" + ], + "producers": [ + "defproducerb" + ], + "dont_start": false + }, + "testnet_02":{ + "name": "testnet_02", + "keys": [ + { + "privkey":"5KkQbdxFHr8Pg1N3DEMDdU7emFgUTwQvh99FDJrodFhUbbsAtQT", + "pubkey":"EOS6Tkpf8kcDfa32WA9B4nTcEJ64ZdDMSNioDcaL6rzdMwnpzaWJB" + } + ], + "peers": [ + "bios", + "testnet_01", + "testnet_00", + "testnet_04" + ], + "producers": [ + "defproducerc" + ], + "dont_start": false + }, + "testnet_03":{ + "name": "testnet_03", + "keys": [ + { + "privkey":"5JxTJJegQBpEL1p77TzkN1ompMB9gDwAfjM9chPzFCB4chxmwrE", + "pubkey":"EOS52ntDHqA2qj4xVo7KmxdezMRhvvBqpZBuKYJCsgihisxmywpAx" + } + ], + "peers": [ + "bios", + "testnet_04" + ], + "producers": [ + "defproducerd" + ], + "dont_start": false + }, + "testnet_04":{ + "name": "testnet_04", + "keys": [ + ], + "peers": [ + "bios", + "testnet_00", + "testnet_01", + "testnet_02", + "testnet_03" + ], + "producers": [ + ], + "dont_start": false + } + } +} diff --git a/tests/large-lib-test.py b/tests/large-lib-test.py deleted file mode 100755 index 6c5138b4b1..0000000000 --- a/tests/large-lib-test.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 - -import random -import signal -import time - -from TestHarness import Cluster, Node, ReturnType, TestHelper, Utils, WalletMgr -from TestHarness.Node import BlockType - -############################################################### -# large-lib-test -# -# Test LIB in a network will advance when an invalid larger LIB -# than current one is received from a speculative node. -# -############################################################### - - -Print=Utils.Print -errorExit=Utils.errorExit - -args=TestHelper.parse_args({"--kill-sig","--kill-count","--keep-logs" - ,"--dump-error-details","-v","--leave-running","--unshared" - }) -pnodes=1 -total_nodes=3 # first one is producer, and last two are speculative nodes -debug=args.v -dumpErrorDetails=args.dump_error_details -relaunchTimeout=10 -# Don't want to set too big, trying to reduce test time, but needs to be large enough for test to finish before -# restart re-creates this many blocks. -numBlocksToProduceBeforeRelaunch=80 -numBlocksToWaitBeforeChecking=20 - -Utils.Debug=debug -testSuccessful=False - -seed=1 -random.seed(seed) # Use a fixed seed for repeatability. -cluster=Cluster(unshared=args.unshared, keepRunning=args.leave_running, keepLogs=args.keep_logs) -walletMgr=WalletMgr(True) -cluster.setWalletMgr(walletMgr) - -def relaunchNode(node: Node, chainArg="", skipGenesis=True, relaunchAssertMessage="Fail to relaunch"): - isRelaunchSuccess=node.relaunch(chainArg=chainArg, timeout=relaunchTimeout, skipGenesis=skipGenesis) - time.sleep(1) # Give a second to replay or resync if needed - assert isRelaunchSuccess, relaunchAssertMessage - return isRelaunchSuccess - -try: - TestHelper.printSystemInfo("BEGIN") - - Print("Stand up cluster") - if cluster.launch( - pnodes=pnodes, - totalNodes=total_nodes, - totalProducers=1, - topo="mesh") is False: - errorExit("Failed to stand up eos cluster.") - - producingNode=cluster.getNode(0) - speculativeNode1=cluster.getNode(1) - speculativeNode2=cluster.getNode(2) - - Print ("Wait for Cluster stabilization") - if not cluster.waitOnClusterBlockNumSync(3): - errorExit("Cluster never stabilized") - Print ("Cluster stabilized") - - Print("Wait for producing {} blocks".format(numBlocksToProduceBeforeRelaunch)) - producingNode.waitForBlock(numBlocksToProduceBeforeRelaunch, blockType=BlockType.lib) - producingNode.waitForProducer("defproducera") - - Print("Kill all node instances.") - for clusterNode in cluster.nodes: - clusterNode.kill(signal.SIGTERM) - cluster.biosNode.kill(signal.SIGTERM) - Print("All nodeos instances killed.") - - # Remove both state and blocks such that no replay happens - Print("Remove producer node's state and blocks directories") - Utils.rmNodeDataDir(0) - Print("Remove the second speculative node's state and blocks directories") - Utils.rmNodeDataDir(2) - - Print ("Relaunch all cluster nodes instances.") - # -e for resuming production, defproducera only producer at this point - # skipGenesis=False for launch the same chain as before - relaunchNode(producingNode, chainArg="-e --sync-fetch-span 5 ", skipGenesis=False) - relaunchNode(speculativeNode1, chainArg="--sync-fetch-span 5 ") - relaunchNode(speculativeNode2, chainArg="--sync-fetch-span 5 ", skipGenesis=False) - - Print("Note LIBs") - prodLib = producingNode.getIrreversibleBlockNum() - specLib1 = speculativeNode1.getIrreversibleBlockNum() - specLib2 = speculativeNode2.getIrreversibleBlockNum() - Print("prodLib {}, specLib1 {}, specLib2 {},".format(prodLib, specLib1, specLib2)) - - Print("Wait for {} blocks to produce".format(numBlocksToWaitBeforeChecking)) - speculativeNode2.waitForBlock( specLib2 + numBlocksToWaitBeforeChecking, blockType=BlockType.lib) - - Print("Check whether LIBs advance or not") - prodLibAfterWait = producingNode.getIrreversibleBlockNum() - specLibAfterWait1 = speculativeNode1.getIrreversibleBlockNum() - specLibAfterWait2 = speculativeNode2.getIrreversibleBlockNum() - Print("prodLibAfterWait {}, specLibAfterWait1 {}, specLibAfterWait2 {},".format(prodLibAfterWait, specLibAfterWait1, specLibAfterWait2)) - - assert prodLibAfterWait > prodLib and specLibAfterWait2 > specLib2, "Either producer ({} -> {})/ second speculative node ({} -> {}) is not advancing".format(prodLib, prodLibAfterWait, specLib2, specLibAfterWait2) - - testSuccessful=True - -finally: - TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, dumpErrorDetails=dumpErrorDetails) - -exitCode = 0 if testSuccessful else 1 -exit(exitCode) diff --git a/tests/lib_advance_test.py b/tests/lib_advance_test.py new file mode 100755 index 0000000000..5525855ebd --- /dev/null +++ b/tests/lib_advance_test.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 + +import time +import decimal +import json +import math +import re +import signal + +from TestHarness import Account, Cluster, Node, TestHelper, Utils, WalletMgr, CORE_SYMBOL +from TestHarness.Node import BlockType + +############################################################### +# lib_advance_test +# +# Setup 4 producers separated by a bridge node. +# Kill bridge node, allow both sides to produce and +# verify they can sync back together after they are +# reconnected. +# +############################################################### +Print=Utils.Print +errorExit=Utils.errorExit + + +args = TestHelper.parse_args({"--dump-error-details","--keep-logs","-v","--leave-running", + "--wallet-port","--unshared"}) +Utils.Debug=args.v +totalProducerNodes=4 +totalNonProducerNodes=1 +totalNodes=totalProducerNodes+totalNonProducerNodes +maxActiveProducers=3 +totalProducers=maxActiveProducers +cluster=Cluster(unshared=args.unshared, keepRunning=args.leave_running, keepLogs=args.keep_logs) +dumpErrorDetails=args.dump_error_details +walletPort=args.wallet_port + +walletMgr=WalletMgr(True, port=walletPort) +testSuccessful=False + +try: + TestHelper.printSystemInfo("BEGIN") + + cluster.setWalletMgr(walletMgr) + 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" + + # *** setup topogrophy *** + + # "bridge" shape connects defproducera (node0) defproducerb (node1) defproducerc (node2) to each other and defproducerd (node3) + # and the only connection between those 2 groups is through the bridge (node4) + if cluster.launch(topo="./tests/bridge_for_fork_test_shape.json", pnodes=totalProducerNodes, + totalNodes=totalNodes, totalProducers=totalProducerNodes, loadSystemContract=False, + specificExtraNodeosArgs=specificExtraNodeosArgs) is False: + Utils.cmdError("launcher") + Utils.errorExit("Failed to stand up eos cluster.") + Print("Validating system accounts after bootstrap") + cluster.validateAccounts(None) + + # *** identify each node (producers and non-producing node) *** + + prodNode0 = cluster.getNode(0) + prodNode1 = cluster.getNode(1) + prodNode2 = cluster.getNode(2) + prodNode3 = cluster.getNode(3) # other side of bridge + nonProdNode = cluster.getNode(4) + + prodNodes=[ prodNode0, prodNode1, prodNode2, prodNode3 ] + + prodA=prodNode0 # defproducera + prodD=prodNode3 # defproducerc + + # *** Identify a block where production is stable *** + + #verify nodes are in sync and advancing + cluster.biosNode.kill(signal.SIGTERM) + cluster.waitOnClusterSync(blockAdvancing=5) + + libProdABeforeKill = prodA.getIrreversibleBlockNum() + libProdDBeforeKill = prodD.getIrreversibleBlockNum() + + # *** Killing the "bridge" node *** + Print('Sending command to kill "bridge" node to separate the 2 producer groups.') + # kill at the beginning of the production window for defproducera, so there is time for the fork for + # defproducerd to grow before it would overtake the fork for defproducera and defproducerb and defproducerc + killAtProducer="defproducera" + nonProdNode.killNodeOnProducer(producer=killAtProducer, whereInSequence=1) + + #verify that the non producing node is not alive (and populate the producer nodes with current getInfo data to report if + #an error occurs) + numPasses = 2 + blocksPerProducer = 12 + blocksPerRound = totalProducers * blocksPerProducer + count = blocksPerRound * numPasses + while nonProdNode.verifyAlive() and count > 0: + # wait on prodNode 0 since it will continue to advance, since defproducera and defproducerb are its producers + Print("Wait for next block") + assert prodA.waitForNextBlock(timeout=6), "Production node A should continue to advance, even after bridge node is killed" + count -= 1 + + assert not nonProdNode.verifyAlive(), "Bridge node should have been killed if test was functioning correctly." + + transferAmount = 10 + # Does not use transaction retry (not needed) + transfer = prodD.transferFunds(cluster.eosioAccount, cluster.defproduceraAccount, f"{transferAmount}.0000 {CORE_SYMBOL}", "fund account") + transBlockNum = transfer['processed']['block_num'] + transId = prodD.getLastTrackedTransactionId() + + beforeBlockNum = prodA.getBlockNum() + prodA.waitForProducer("defproducera") + prodA.waitForProducer("defproducerb") + prodA.waitForProducer("defproducera") + prodA.waitForProducer("defproducerc") # produce enough that sync will have over 30 blocks to sync + assert prodA.waitForLibToAdvance(), "Production node A should advance lib without D" + assert prodD.waitForNextBlock(), "Production node D should continue to advance, even after bridge node is killed" + afterBlockNum = prodA.getBlockNum() + + Print("Relaunching the non-producing bridge node to connect the nodes") + if not nonProdNode.relaunch(): + errorExit(f"Failure - (non-production) node {nonProdNode.nodeNum} should have restarted") + + while prodD.getInfo()['last_irreversible_block_num'] < transBlockNum: + Print("Wait for LIB to move, which indicates prodD may have forked out the branch") + assert prodD.waitForLibToAdvance(60), \ + "ERROR: Network did not reach consensus after bridge node was restarted." + + assert prodD.waitForLibToAdvance() + assert prodD.waitForProducer("defproducera") + assert prodA.waitForProducer("defproducerd") + + for prodNode in prodNodes: + info=prodNode.getInfo() + Print(f"node info: {json.dumps(info, indent=1)}") + + assert prodA.getIrreversibleBlockNum() > max(libProdABeforeKill, libProdDBeforeKill) + assert prodD.getIrreversibleBlockNum() > max(libProdABeforeKill, libProdDBeforeKill) + + logFile = Utils.getNodeDataDir(prodNode3.nodeId) + "/stderr.txt" + f = open(logFile) + contents = f.read() + if contents.count("3030001 unlinkable_block_exception: Unlinkable block") > (afterBlockNum-beforeBlockNum): # a few are fine + errorExit(f"Node{prodNode3.nodeId} has more than {afterBlockNum-beforeBlockNum} unlinkable blocks: {logFile}.") + + testSuccessful=True +finally: + TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, dumpErrorDetails=dumpErrorDetails) + +errorCode = 0 if testSuccessful else 1 +exit(errorCode) diff --git a/tests/p2p_high_latency_test.py b/tests/p2p_high_latency_test.py index 2b8028209c..d6326d4fe9 100644 --- a/tests/p2p_high_latency_test.py +++ b/tests/p2p_high_latency_test.py @@ -68,7 +68,7 @@ def exec(cmd): try: TestHelper.printSystemInfo("BEGIN") - traceNodeosArgs=" --plugin eosio::producer_plugin --produce-block-offset-ms 0 --producer-threads 1 --plugin eosio::net_plugin --net-threads 1" + traceNodeosArgs=" --plugin eosio::producer_plugin --produce-block-offset-ms 0 --plugin eosio::net_plugin --net-threads 1" if cluster.launch(pnodes=1, totalNodes=totalNodes, totalProducers=1, specificExtraNodeosArgs=specificExtraNodeosArgs, extraNodeosArgs=traceNodeosArgs) is False: Utils.cmdError("launcher") Utils.errorExit("Failed to stand up eos cluster.") diff --git a/tests/ship_streamer_test.py b/tests/ship_streamer_test.py index 710ab90db4..7b38f501ec 100755 --- a/tests/ship_streamer_test.py +++ b/tests/ship_streamer_test.py @@ -155,6 +155,22 @@ def getLatestSnapshot(nodeId): Print("Shutdown unneeded bios node") cluster.biosNode.kill(signal.SIGTERM) + Print("Create a jumbo row") + contract = "jumborow" + contractDir = "unittests/contracts/%s" % (contract) + wasmFile = "%s.wasm" % (contract) + abiFile = "%s.abi" % (contract) + + nonProdNode.publishContract(accounts[0], contractDir, wasmFile, abiFile) + jumbotxn = { + + "actions": [{"account": "testeraaaaaa","name": "jumbotime", + "authorization": [{"actor": "testeraaaaaa","permission": "active"}], + "data": "", + "compression": "none"}] + } + nonProdNode.pushTransaction(jumbotxn) + Print("Configure and launch txn generators") targetTpsPerGenerator = 10 testTrxGenDurationSec=60*60 diff --git a/tests/trace_plugin_test.py b/tests/trace_plugin_test.py index 1bfe110c60..995bca74eb 100755 --- a/tests/trace_plugin_test.py +++ b/tests/trace_plugin_test.py @@ -117,6 +117,7 @@ def setUpClass(self): @classmethod def tearDownClass(self): TraceApiPluginTest.cluster.testFailed = not testSuccessful + TraceApiPluginTest.cluster.shutdown() if __name__ == "__main__": unittest.main() diff --git a/tutorials/bios-boot-tutorial/accounts.json b/tutorials/bios-boot-tutorial/accounts.json old mode 100755 new mode 100644 diff --git a/unittests/api_tests.cpp b/unittests/api_tests.cpp index 20eced06f6..598f230bdd 100644 --- a/unittests/api_tests.cpp +++ b/unittests/api_tests.cpp @@ -1470,8 +1470,10 @@ void transaction_tests(T& chain) { auto& t = std::get<0>(x); if (t && t->receipt && t->receipt->status != transaction_receipt::executed) { trace = t; } } ); - block_state_ptr bsp; - auto c2 = chain.control->accepted_block.connect([&](const block_state_ptr& b) { bsp = b; }); + signed_block_ptr block; + auto c2 = chain.control->accepted_block.connect([&](block_signal_params t) { + const auto& [ b, id ] = t; + block = b; }); // test error handling on deferred transaction failure auto test_trace = CALL_TEST_FUNCTION(chain, "test_transaction", "send_transaction_trigger_error_handler", {}); @@ -1480,7 +1482,7 @@ void transaction_tests(T& chain) { BOOST_CHECK_EQUAL(trace->receipt->status, transaction_receipt::soft_fail); std::set block_ids; - for( const auto& receipt : bsp->block->transactions ) { + for( const auto& receipt : block->transactions ) { transaction_id_type id; if( std::holds_alternative(receipt.trx) ) { const auto& pt = std::get(receipt.trx); diff --git a/unittests/block_tests.cpp b/unittests/block_tests.cpp index 2236758dcf..d75832ac09 100644 --- a/unittests/block_tests.cpp +++ b/unittests/block_tests.cpp @@ -217,11 +217,13 @@ BOOST_AUTO_TEST_CASE(broadcasted_block_test) signed_block_ptr bcasted_blk_by_prod_node; signed_block_ptr bcasted_blk_by_recv_node; - producer_node.control->accepted_block.connect( [&](const block_state_ptr& bs) { - bcasted_blk_by_prod_node = bs->block; + producer_node.control->accepted_block.connect( [&](block_signal_params t) { + const auto& [ block, id ] = t; + bcasted_blk_by_prod_node = block; }); - receiving_node.control->accepted_block.connect( [&](const block_state_ptr& bs) { - bcasted_blk_by_recv_node = bs->block; + receiving_node.control->accepted_block.connect( [&](block_signal_params t) { + const auto& [ block, id ] = t; + bcasted_blk_by_recv_node = block; }); auto b = producer_node.produce_block(); diff --git a/unittests/chain_tests.cpp b/unittests/chain_tests.cpp index 7079baac99..05fb688e3a 100644 --- a/unittests/chain_tests.cpp +++ b/unittests/chain_tests.cpp @@ -149,41 +149,53 @@ BOOST_AUTO_TEST_CASE( signal_validated_blocks ) try { tester chain; tester validator; - block_state_ptr accepted_bsp; - auto c = chain.control->accepted_block.connect([&](const block_state_ptr& b) { - BOOST_CHECK(b); - BOOST_CHECK(chain.control->fetch_block_state_by_id(b->id) == b); - BOOST_CHECK(chain.control->fetch_block_state_by_number(b->block_num) == b); // verify it can be found (has to be validated) - BOOST_CHECK(chain.control->fetch_block_by_id(b->id) == b->block); - BOOST_CHECK(chain.control->fetch_block_by_number(b->block_num) == b->block); - BOOST_REQUIRE(chain.control->fetch_block_header_by_number(b->block_num)); - BOOST_CHECK(chain.control->fetch_block_header_by_number(b->block_num)->calculate_id() == b->id); - BOOST_REQUIRE(chain.control->fetch_block_header_by_id(b->id)); - BOOST_CHECK(chain.control->fetch_block_header_by_id(b->id)->calculate_id() == b->id); - accepted_bsp = b; + signed_block_ptr accepted_block; + block_id_type accepted_id; + auto c = chain.control->accepted_block.connect([&](block_signal_params t) { + const auto& [ block, id ] = t; + auto block_num = block->block_num(); + BOOST_CHECK(block); + const auto& bsp_by_id = chain.control->fetch_block_state_by_id(id); + BOOST_CHECK(bsp_by_id->block_num == block_num); + const auto& bsp_by_number = chain.control->fetch_block_state_by_number(block_num); // verify it can be found (has to be validated) + BOOST_CHECK(bsp_by_number->id == id); + BOOST_CHECK(chain.control->fetch_block_by_id(id) == block); + BOOST_CHECK(chain.control->fetch_block_by_number(block_num) == block); + BOOST_REQUIRE(chain.control->fetch_block_header_by_number(block_num)); + BOOST_CHECK(chain.control->fetch_block_header_by_number(block_num)->calculate_id() == id); + BOOST_REQUIRE(chain.control->fetch_block_header_by_id(id)); + BOOST_CHECK(chain.control->fetch_block_header_by_id(id)->calculate_id() == id); + accepted_block = block; + accepted_id = id; }); - block_state_ptr validated_bsp; - auto c2 = validator.control->accepted_block.connect([&](const block_state_ptr& b) { - BOOST_CHECK(b); - BOOST_CHECK(validator.control->fetch_block_state_by_id(b->id) == b); - BOOST_CHECK(validator.control->fetch_block_state_by_number(b->block_num) == b); // verify it can be found (has to be validated) - BOOST_CHECK(validator.control->fetch_block_by_id(b->id) == b->block); - BOOST_CHECK(validator.control->fetch_block_by_number(b->block_num) == b->block); - BOOST_REQUIRE(validator.control->fetch_block_header_by_number(b->block_num)); - BOOST_CHECK(validator.control->fetch_block_header_by_number(b->block_num)->calculate_id() == b->id); - BOOST_REQUIRE(validator.control->fetch_block_header_by_id(b->id)); - BOOST_CHECK(validator.control->fetch_block_header_by_id(b->id)->calculate_id() == b->id); - validated_bsp = b; + signed_block_ptr validated_block; + block_id_type validated_id; + auto c2 = validator.control->accepted_block.connect([&](block_signal_params t) { + const auto& [ block, id ] = t; + auto block_num = block->block_num(); + BOOST_CHECK(block); + const auto& bsp_by_id = validator.control->fetch_block_state_by_id(id); + BOOST_CHECK(bsp_by_id->block_num == block_num); + const auto& bsp_by_number = validator.control->fetch_block_state_by_number(block_num); // verify it can be found (has to be validated) + BOOST_CHECK(bsp_by_number->id == id); + BOOST_CHECK(validator.control->fetch_block_by_id(id) == block); + BOOST_CHECK(validator.control->fetch_block_by_number(block_num) == block); + BOOST_REQUIRE(validator.control->fetch_block_header_by_number(block_num)); + BOOST_CHECK(validator.control->fetch_block_header_by_number(block_num)->calculate_id() == id); + BOOST_REQUIRE(validator.control->fetch_block_header_by_id(id)); + BOOST_CHECK(validator.control->fetch_block_header_by_id(id)->calculate_id() == id); + validated_block = block; + validated_id = id; }); chain.produce_blocks(1); - validator.push_block(accepted_bsp->block); + validator.push_block(accepted_block); chain.create_account("hello"_n); auto produced_block = chain.produce_block(); - validator.push_block(accepted_bsp->block); - BOOST_CHECK(produced_block->calculate_id() == accepted_bsp->id); - BOOST_CHECK(accepted_bsp->id == validated_bsp->id); + validator.push_block(accepted_block); + BOOST_CHECK(produced_block->calculate_id() == accepted_id); + BOOST_CHECK(accepted_id == validated_id); } FC_LOG_AND_RETHROW() diff --git a/unittests/contracts/CMakeLists.txt b/unittests/contracts/CMakeLists.txt index 289450ccf1..ae0c483d71 100644 --- a/unittests/contracts/CMakeLists.txt +++ b/unittests/contracts/CMakeLists.txt @@ -26,3 +26,4 @@ add_subdirectory(eosio.system) add_subdirectory(eosio.token) add_subdirectory(eosio.wrap) add_subdirectory(eosio.mechanics) +add_subdirectory(jumborow) \ No newline at end of file diff --git a/unittests/contracts/eosio.mechanics/eosmechanics.wasm b/unittests/contracts/eosio.mechanics/eosmechanics.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/eosio.msig/eosio.msig.wasm b/unittests/contracts/eosio.msig/eosio.msig.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/eosio.system/eosio.system.wasm b/unittests/contracts/eosio.system/eosio.system.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/eosio.token/eosio.token.wasm b/unittests/contracts/eosio.token/eosio.token.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/eosio.wrap/eosio.wrap.wasm b/unittests/contracts/eosio.wrap/eosio.wrap.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/getcode_deepindent.wasm b/unittests/contracts/getcode_deepindent.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/jumborow/CMakeLists.txt b/unittests/contracts/jumborow/CMakeLists.txt new file mode 100644 index 0000000000..f0a14a49ea --- /dev/null +++ b/unittests/contracts/jumborow/CMakeLists.txt @@ -0,0 +1,2 @@ +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/jumborow.wasm ${CMAKE_CURRENT_BINARY_DIR}/jumborow.wasm COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/jumborow.abi ${CMAKE_CURRENT_BINARY_DIR}/jumborow.abi COPYONLY ) diff --git a/unittests/contracts/jumborow/jumborow.abi b/unittests/contracts/jumborow/jumborow.abi new file mode 100644 index 0000000000..c8f7eaac7c --- /dev/null +++ b/unittests/contracts/jumborow/jumborow.abi @@ -0,0 +1,23 @@ +{ + "version": "eosio::abi/1.0", + "types": [], + "structs": [{ + "name": "jumbo", + "base": "", + "fields": [] + } + ], + "actions": [{ + "name": "jumbotime", + "type": "jumbo", + "ricardian_contract": "" + } + ], + "tables": [], + "ricardian_clauses": [], + "error_messages": [], + "abi_extensions": [], + "variants": [], + "action_results": [] +} + diff --git a/unittests/contracts/jumborow/jumborow.wasm b/unittests/contracts/jumborow/jumborow.wasm new file mode 100644 index 0000000000..050ccce0bb Binary files /dev/null and b/unittests/contracts/jumborow/jumborow.wasm differ diff --git a/unittests/contracts/jumborow/jumborow.wast b/unittests/contracts/jumborow/jumborow.wast new file mode 100644 index 0000000000..d9f0838e58 --- /dev/null +++ b/unittests/contracts/jumborow/jumborow.wast @@ -0,0 +1,8 @@ +(module + (import "env" "db_store_i64" (func $db_store_i64 (param i64 i64 i64 i64 i32 i32) (result i32))) + (memory $0 528) + (export "apply" (func $apply)) + (func $apply (param $receiver i64) (param $account i64) (param $action_name i64) + (drop (call $db_store_i64 (local.get $receiver) (local.get $receiver) (local.get $receiver) (i64.const 0) (i32.const 1) (i32.const 34603007))) + ) +) diff --git a/unittests/contracts/locals-yc.wasm b/unittests/contracts/locals-yc.wasm old mode 100755 new mode 100644 diff --git a/unittests/contracts/test_wasts.hpp b/unittests/contracts/test_wasts.hpp index 1eab70405e..94f5a9f249 100644 --- a/unittests/contracts/test_wasts.hpp +++ b/unittests/contracts/test_wasts.hpp @@ -990,4 +990,15 @@ static const char negative_memory_grow_trap_wast[] = R"=====( ) ) ) +)====="; + +static const char set_jumbo_row_wast[] = R"=====( +(module + (import "env" "db_store_i64" (func $db_store_i64 (param i64 i64 i64 i64 i32 i32) (result i32))) + (memory $0 528) + (export "apply" (func $apply)) + (func $apply (param $receiver i64) (param $account i64) (param $action_name i64) + (drop (call $db_store_i64 (get_local $receiver) (get_local $receiver) (get_local $receiver) (i64.const 0) (i32.const 1) (i32.const 34603007))) + ) +) )====="; \ No newline at end of file diff --git a/unittests/eosvmoc_limits_tests.cpp b/unittests/eosvmoc_limits_tests.cpp index 72ec3c0700..1614ecd974 100644 --- a/unittests/eosvmoc_limits_tests.cpp +++ b/unittests/eosvmoc_limits_tests.cpp @@ -98,6 +98,8 @@ BOOST_AUTO_TEST_CASE( limits_not_enforced ) { try { limit_not_violated_test(eosvmoc_config); } FC_LOG_AND_RETHROW() } +// UBSAN & ASAN can add massive virtual memory usage; skip this test when either are enabled +#if !__has_feature(undefined_behavior_sanitizer) && !__has_feature(address_sanitizer) // test VM limit are checked BOOST_AUTO_TEST_CASE( vm_limit ) { try { eosvmoc::config eosvmoc_config = make_eosvmoc_config_without_limits(); @@ -111,6 +113,14 @@ BOOST_AUTO_TEST_CASE( vm_limit ) { try { limit_not_violated_test(eosvmoc_config); } FC_LOG_AND_RETHROW() } +//make sure vm_limit is populated for a default constructed config (what nodeos will use) +BOOST_AUTO_TEST_CASE( check_config_default_vm_limit ) { try { + eosvmoc::config eosvmoc_config; + + BOOST_REQUIRE(eosvmoc_config.vm_limit); +} FC_LOG_AND_RETHROW() } +#endif + // test stack size limit is checked BOOST_AUTO_TEST_CASE( stack_limit ) { try { eosvmoc::config eosvmoc_config = make_eosvmoc_config_without_limits(); diff --git a/unittests/forked_tests.cpp b/unittests/forked_tests.cpp index b375773391..57ffa266ec 100644 --- a/unittests/forked_tests.cpp +++ b/unittests/forked_tests.cpp @@ -351,10 +351,15 @@ BOOST_AUTO_TEST_CASE( validator_accepts_valid_blocks ) try { auto id = n1.control->head_block_id(); - block_state_ptr first_block; - - auto c = n2.control->accepted_block.connect( [&]( const block_state_ptr& bsp) { - first_block = bsp; + signed_block_ptr first_block; + block_id_type first_id; + signed_block_header first_header; + + auto c = n2.control->accepted_block.connect( [&]( block_signal_params t ) { + const auto& [ block, id ] = t; + first_block = block; + first_id = id; + first_header = static_cast(*block); } ); push_blocks( n1, n2 ); @@ -362,13 +367,14 @@ BOOST_AUTO_TEST_CASE( validator_accepts_valid_blocks ) try { BOOST_CHECK_EQUAL( n2.control->head_block_id(), id ); BOOST_REQUIRE( first_block ); - first_block->verify_signee(); - BOOST_CHECK_EQUAL( first_block->header.calculate_id(), first_block->block->calculate_id() ); - BOOST_CHECK( first_block->header.producer_signature == first_block->block->producer_signature ); + const auto& first_bsp = n2.control->fetch_block_state_by_id(first_id); + first_bsp->verify_signee(); + BOOST_CHECK_EQUAL( first_header.calculate_id(), first_block->calculate_id() ); + BOOST_CHECK( first_header.producer_signature == first_block->producer_signature ); c.disconnect(); - n3.push_block( first_block->block ); + n3.push_block( first_block ); BOOST_CHECK_EQUAL( n3.control->head_block_id(), id ); @@ -697,8 +703,9 @@ BOOST_AUTO_TEST_CASE( push_block_returns_forked_transactions ) try { // test forked blocks signal accepted_block in order, required by trace_api_plugin std::vector accepted_blocks; - auto conn = c.control->accepted_block.connect( [&]( const block_state_ptr& bsp) { - accepted_blocks.emplace_back( bsp->block ); + auto conn = c.control->accepted_block.connect( [&]( block_signal_params t ) { + const auto& [ block, id ] = t; + accepted_blocks.emplace_back( block ); } ); // dan on chain 1 now gets all of the blocks from chain 2 which should cause fork switch diff --git a/unittests/misc_tests.cpp b/unittests/misc_tests.cpp index 2877ca491c..7649dcbfd0 100644 --- a/unittests/misc_tests.cpp +++ b/unittests/misc_tests.cpp @@ -400,7 +400,8 @@ BOOST_AUTO_TEST_CASE(authority_checker) auto b = test.get_public_key(name("b"), "active"); auto c = test.get_public_key(name("c"), "active"); - auto GetNullAuthority = [](auto){abort(); return authority();}; + const authority null_authority; + auto GetNullAuthority = [&null_authority](auto){abort(); return &null_authority;}; auto A = authority(2, {key_weight{a, 1}, key_weight{b, 1}}); { @@ -450,8 +451,9 @@ BOOST_AUTO_TEST_CASE(authority_checker) BOOST_TEST(make_auth_checker(GetNullAuthority, 2, {b}).satisfied(A)); BOOST_TEST(!make_auth_checker(GetNullAuthority, 2, {c}).satisfied(A)); - auto GetCAuthority = [c](auto){ - return authority(1, {key_weight{c, 1}}); + const authority c_authority = authority(1, {key_weight{c, 1}}); + auto GetCAuthority = [&c_authority](auto){ + return &c_authority; }; A = authority(2, {key_weight{a, 2}, key_weight{b, 1}}, {permission_level_weight{{name("hello"), name("world")}, 1}}); @@ -544,10 +546,13 @@ BOOST_AUTO_TEST_CASE(authority_checker) auto d = test.get_public_key(name("d"), "active"); auto e = test.get_public_key(name("e"), "active"); - auto GetAuthority = [d, e] (const permission_level& perm) { + const authority auth_for_top_actor = authority(2, {key_weight{d, 1}}, {permission_level_weight{{name("bottom"), name("bottom")}, 1}}); + const authority auth_for_others = authority{1, {{e, 1}}, {}}; + + auto GetAuthority = [&auth_for_top_actor, &auth_for_others] (const permission_level& perm) { if (perm.actor == name("top")) - return authority(2, {key_weight{d, 1}}, {permission_level_weight{{name("bottom"), name("bottom")}, 1}}); - return authority{1, {{e, 1}}, {}}; + return &auth_for_top_actor; + return &auth_for_others; }; A = authority(5, {key_weight{a, 2}, key_weight{b, 2}, key_weight{c, 2}}, {permission_level_weight{{name("top"), name("top")}, 5}}); diff --git a/unittests/snapshot_tests.cpp b/unittests/snapshot_tests.cpp index 5e25220161..710db93312 100644 --- a/unittests/snapshot_tests.cpp +++ b/unittests/snapshot_tests.cpp @@ -11,6 +11,7 @@ #include #include +#include "test_wasts.hpp" using namespace eosio; using namespace testing; @@ -653,4 +654,37 @@ BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) remove(json_snap_path); } +BOOST_AUTO_TEST_CASE_TEMPLATE(jumbo_row, SNAPSHOT_SUITE, snapshot_suites) +{ + fc::temp_directory tempdir; + auto config = tester::default_config(tempdir); + config.first.state_size = 64*1024*1024; + tester chain(config.first, config.second); + chain.execute_setup_policy(setup_policy::full); + + chain.create_accounts({"jumbo"_n}); + chain.set_code("jumbo"_n, set_jumbo_row_wast); + chain.produce_blocks(1); + + signed_transaction trx; + action act; + act.account = "jumbo"_n; + act.name = "jumbo"_n; + act.authorization = vector{{"jumbo"_n,config::active_name}}; + trx.actions.push_back(act); + + chain.set_transaction_headers(trx); + trx.sign(tester::get_private_key("jumbo"_n, "active"), chain.control->get_chain_id()); + chain.push_transaction(trx); + chain.produce_blocks(1); + + chain.control->abort_block(); + + auto writer = SNAPSHOT_SUITE::get_writer(); + chain.control->write_snapshot(writer); + auto snapshot = SNAPSHOT_SUITE::finalize(writer); + + snapshotted_tester sst(chain.get_config(), SNAPSHOT_SUITE::get_reader(snapshot), 0); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/unittests/state_history_tests.cpp b/unittests/state_history_tests.cpp index 51f78df9c0..2114bf7647 100644 --- a/unittests/state_history_tests.cpp +++ b/unittests/state_history_tests.cpp @@ -631,16 +631,17 @@ struct state_history_tester : state_history_tester_logs, tester { trace_converter.add_transaction(std::get<0>(t), std::get<1>(t)); }); - control.accepted_block.connect([&](const block_state_ptr& block_state) { + control.accepted_block.connect([&](block_signal_params t) { + const auto& [ block, id ] = t; eosio::state_history_log_header header{.magic = eosio::ship_magic(eosio::ship_current_version, 0), - .block_id = block_state->id, + .block_id = id, .payload_size = 0}; - traces_log.pack_and_write_entry(header, block_state->block->previous, [this, &block_state](auto&& buf) { - trace_converter.pack(buf, false, block_state); + traces_log.pack_and_write_entry(header, block->previous, [this, &block](auto&& buf) { + trace_converter.pack(buf, false, block); }); - chain_state_log.pack_and_write_entry(header, block_state->header.previous, [&control](auto&& buf) { + chain_state_log.pack_and_write_entry(header, block->previous, [&control](auto&& buf) { eosio::state_history::pack_deltas(buf, control.db(), true); }); }); diff --git a/unittests/test-contracts/action_results/action_results.wasm b/unittests/test-contracts/action_results/action_results.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/asserter/asserter.wasm b/unittests/test-contracts/asserter/asserter.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/bls_primitives_test/bls_primitives_test.wasm b/unittests/test-contracts/bls_primitives_test/bls_primitives_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/crypto_primitives_test/crypto_primitives_test.wasm b/unittests/test-contracts/crypto_primitives_test/crypto_primitives_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/deferred_test/deferred_test.wasm b/unittests/test-contracts/deferred_test/deferred_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/get_block_num_test/get_block_num_test.wasm b/unittests/test-contracts/get_block_num_test/get_block_num_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/get_sender_test/get_sender_test.wasm b/unittests/test-contracts/get_sender_test/get_sender_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.wasm b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/get_table_test/get_table_test.wasm b/unittests/test-contracts/get_table_test/get_table_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/integration_test/integration_test.wasm b/unittests/test-contracts/integration_test/integration_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/nested_container_multi_index/nested_container_multi_index.wasm b/unittests/test-contracts/nested_container_multi_index/nested_container_multi_index.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/no_auth_table/no_auth_table.wasm b/unittests/test-contracts/no_auth_table/no_auth_table.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/noop/noop.wasm b/unittests/test-contracts/noop/noop.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/params_test/params_test.wasm b/unittests/test-contracts/params_test/params_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/payloadless/payloadless.wasm b/unittests/test-contracts/payloadless/payloadless.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/proxy/proxy.wasm b/unittests/test-contracts/proxy/proxy.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/ram_restrictions_test/ram_restrictions_test.wasm b/unittests/test-contracts/ram_restrictions_test/ram_restrictions_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/reject_all/reject_all.wasm b/unittests/test-contracts/reject_all/reject_all.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/restrict_action_test/restrict_action_test.wasm b/unittests/test-contracts/restrict_action_test/restrict_action_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/snapshot_test/snapshot_test.wasm b/unittests/test-contracts/snapshot_test/snapshot_test.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/test_api/test_api.wasm b/unittests/test-contracts/test_api/test_api.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/test_api_db/test_api_db.wasm b/unittests/test-contracts/test_api_db/test_api_db.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/test_api_multi_index/test_api_multi_index.wasm b/unittests/test-contracts/test_api_multi_index/test_api_multi_index.wasm old mode 100755 new mode 100644 diff --git a/unittests/test-contracts/wasm_config_bios/wasm_config_bios.wasm b/unittests/test-contracts/wasm_config_bios/wasm_config_bios.wasm old mode 100755 new mode 100644 diff --git a/unittests/test_chainbase_types.cpp b/unittests/test_chainbase_types.cpp new file mode 100644 index 0000000000..ff4760344f --- /dev/null +++ b/unittests/test_chainbase_types.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include +#include +#include + +namespace bip = boost::interprocess; +namespace fs = std::filesystem; + +using namespace chainbase; + +template +using bip_vector = bip::vector; + +using shared_string_vector = shared_vector; + +struct book { + shared_string title; + shared_string_vector authors; + + bool operator==(const book&) const = default; +}; + +FC_REFLECT(book, (title)(authors)) + +namespace fc::raw { + template + inline void pack(Stream& s, const book& b) { + fc::raw::pack(s, b.title); + fc::raw::pack(s, b.authors); + } + + template + inline void unpack(Stream& s, book& b) { + fc::raw::unpack(s, b.title); + fc::raw::unpack(s, b.authors); + } +} + +template +void check_pack_unpack(V &v, V &v2) { + v.emplace_back(shared_string("Moby Dick"), shared_string_vector{ "Herman Melville" }); + v.emplace_back(shared_string("All the President's Men"), shared_string_vector{ "Carl Bernstein", "Bob Woodward" }); + + BOOST_REQUIRE(v[1].title == "All the President's Men"); + BOOST_REQUIRE(v[1].authors[1] == "Bob Woodward"); + + // try pack/unpack + constexpr size_t buffsz = 4096; + char buf[buffsz]; + fc::datastream ds(buf, buffsz); + + fc::raw::pack(ds, v); + ds.seekp(0); + fc::raw::unpack(ds, v2); + BOOST_REQUIRE(v2[1].title == "All the President's Men"); + BOOST_REQUIRE(v2[1].authors[1] == "Bob Woodward"); + BOOST_REQUIRE(v == v2); +} + +BOOST_AUTO_TEST_CASE(chainbase_type_heap_alloc) { + std::vector v, v2; + check_pack_unpack(v, v2); + + // check that objects inside the vectors are allocated within theheap + BOOST_REQUIRE(!v[1].title.get_allocator()); + BOOST_REQUIRE(!v2[1].authors[0].get_allocator()); +} + +BOOST_AUTO_TEST_CASE(chainbase_type_segment_alloc) { + fc::temp_directory temp_dir; + fs::path temp = temp_dir.path() / "pinnable_mapped_file_101"; + + pinnable_mapped_file pmf(temp, true, 1024 * 1024, false, pinnable_mapped_file::map_mode::mapped); + chainbase::allocator alloc(pmf.get_segment_manager()); + bip_vector> v(alloc); + bip_vector> v2(alloc); + + check_pack_unpack(v, v2); + auto a = v[1].title.get_allocator(); + auto a2 = v2[1].authors[0].get_allocator(); + + // check that objects inside the vectors are allocated within the pinnable_mapped_file segment + BOOST_REQUIRE(a && (chainbase::allocator)(*a) == alloc); + BOOST_REQUIRE(a2 && (chainbase::allocator)(*a2) == alloc); +} diff --git a/unittests/unapplied_transaction_queue_tests.cpp b/unittests/unapplied_transaction_queue_tests.cpp index 5665a9246b..5d91202698 100644 --- a/unittests/unapplied_transaction_queue_tests.cpp +++ b/unittests/unapplied_transaction_queue_tests.cpp @@ -43,7 +43,7 @@ auto create_test_block_state( deque trx_metas ) { auto priv_key = eosio::testing::base_tester::get_private_key( block->producer, "active" ); auto pub_key = eosio::testing::base_tester::get_public_key( block->producer, "active" ); - auto prev = std::make_shared(); + auto prev = std::make_shared(); auto header_bmroot = digest_type::hash( std::make_pair( block->digest(), prev->blockroot_merkle.get_root() ) ); auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, prev->pending_schedule.schedule_hash) ); block->producer_signature = priv_key.sign( sig_digest ); @@ -58,12 +58,12 @@ auto create_test_block_state( deque trx_metas ) { result.emplace_back(k.sign(d)); return result; }; - pending_block_header_state pbhs; + pending_block_header_state_legacy pbhs; pbhs.producer = block->producer; producer_authority_schedule schedule = { 0, { producer_authority{block->producer, block_signing_authority_v0{ 1, {{pub_key, 1}} } } } }; pbhs.active_schedule = schedule; pbhs.valid_block_signing_authority = block_signing_authority_v0{ 1, {{pub_key, 1}} }; - auto bsp = std::make_shared( + auto bsp = std::make_shared( std::move( pbhs ), std::move( block ), std::move( trx_metas ), @@ -124,7 +124,8 @@ BOOST_AUTO_TEST_CASE( unapplied_transaction_queue_test ) try { // clear applied q.add_aborted( { trx1, trx2, trx3 } ); - q.clear_applied( create_test_block_state( { trx1, trx3, trx4 } ) ); + auto bs0 = create_test_block_state( { trx1, trx3, trx4 } ); + q.clear_applied( bs0->block ); BOOST_CHECK( q.size() == 1u ); BOOST_REQUIRE( next( q ) == trx2 ); BOOST_CHECK( q.size() == 0u );