diff --git a/.github/workflows/analyzers.yml b/.github/workflows/analyzers.yml index 8531a16032..52d9bb3829 100644 --- a/.github/workflows/analyzers.yml +++ b/.github/workflows/analyzers.yml @@ -1,36 +1,51 @@ name: Static Analyzers -on: [push, pull_request] +on: [ push, pull_request ] jobs: clang_format: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 - - name: Installing clang-format 12 + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 + + - name: Installing clang-format env: DEBIAN_FRONTEND: noninteractive - run: sudo apt-get install clang-format-12 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 17 + sudo apt install clang-format-17 + - name: Check clang-format run: ci/clang-format-check.sh - + + cmake_format: runs-on: ubuntu-20.04 if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 - - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 #v4.3.0 - with: + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 #v3.1.0 + + - name: Setup Python + uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 #v4.3.0 + with: python-version: '3.x' architecture: 'x64' - - uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 - with: + + - name: Install cmake-format + uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 + with: packages: | cmake-format + - name: Check cmake-format run: ci/cmake-format-check.sh + code_inspector: runs-on: ubuntu-20.04 if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository diff --git a/.github/workflows/artifacts_build_deploy.yml b/.github/workflows/artifacts_build_deploy.yml index 12c499a7ce..b7dcb1d902 100644 --- a/.github/workflows/artifacts_build_deploy.yml +++ b/.github/workflows/artifacts_build_deploy.yml @@ -36,8 +36,8 @@ jobs: osx_job: needs: prepare_build - if: ${{ needs.prepare_build.outputs.tag_created == 'true' }} - runs-on: macOS-12 + if: ${{ needs.prepare_build.outputs.TAG_CREATED == 'true' }} + runs-on: macOS-14 timeout-minutes: 90 strategy: matrix: diff --git a/.github/workflows/code_sanitizers.yml b/.github/workflows/code_sanitizers.yml index d98587aa11..c82c31b280 100644 --- a/.github/workflows/code_sanitizers.yml +++ b/.github/workflows/code_sanitizers.yml @@ -1,6 +1,6 @@ name: Code Sanitizers -on: [push, pull_request, workflow_dispatch] +on: [ push, pull_request, workflow_dispatch ] jobs: linux_sanitizers: @@ -9,13 +9,14 @@ jobs: strategy: fail-fast: false matrix: - BACKEND: [lmdb, rocksdb] - COMPILER: [clang] + BACKEND: [ lmdb, rocksdb ] + COMPILER: [ clang ] SANITIZER: - { name: UBSAN, ignore_errors: false } - - { name: ASAN, ignore_errors: true } - - { name: ASAN_INT, ignore_errors: true } + - { name: ASAN, ignore_errors: false, leak_check: false } + - { name: ASAN_INT, ignore_errors: true, leak_check: false } - { name: TSAN, ignore_errors: true } + - { name: LEAK, ignore_errors: true, leak_check: true } runs-on: ubuntu-22.04 env: COMPILER: ${{ matrix.COMPILER }} @@ -24,7 +25,7 @@ jobs: IGNORE_ERRORS: ${{ matrix.SANITIZER.ignore_errors }} TEST_USE_ROCKSDB: ${{ matrix.BACKEND == 'rocksdb' && '1' || '0' }} DEADLINE_SCALE_FACTOR: ${{ matrix.BACKEND == 'rocksdb' && '2' || '1' }} - ASAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:suppressions=../asan_suppressions + ASAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:suppressions=../asan_suppressions:detect_leaks=${{ matrix.SANITIZER.leak_check && '1' || '0' }} TSAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:suppressions=../tsan_suppressions UBSAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:print_stacktrace=1 if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository @@ -58,3 +59,60 @@ jobs: continue-on-error: ${{ env.IGNORE_ERRORS == 'true' }} run: ../ci/tests/show-sanitizer-reports.sh working-directory: build + + + macos_sanitizers: + name: macOS [${{ matrix.SANITIZER.name }}] [${{ matrix.BACKEND }} | ${{ matrix.COMPILER }}] ${{ matrix.SANITIZER.ignore_errors && ' (Errors Ignored)' || '' }} + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + BACKEND: [ lmdb, rocksdb ] + COMPILER: [ clang ] + SANITIZER: + - { name: UBSAN, ignore_errors: false } + - { name: ASAN, ignore_errors: false } + - { name: TSAN, ignore_errors: true } + runs-on: macos-14 + env: + COMPILER: ${{ matrix.COMPILER }} + BACKEND: ${{ matrix.BACKEND }} + SANITIZER: ${{ matrix.SANITIZER.name }} + IGNORE_ERRORS: ${{ matrix.SANITIZER.ignore_errors }} + TEST_USE_ROCKSDB: ${{ matrix.BACKEND == 'rocksdb' && '1' || '0' }} + DEADLINE_SCALE_FACTOR: ${{ matrix.BACKEND == 'rocksdb' && '2' || '1' }} + ASAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:suppressions=../asan_suppressions + TSAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:suppressions=../tsan_suppressions + UBSAN_OPTIONS: log_exe_name=1:log_path=sanitizer_report:print_stacktrace=1 + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: "recursive" + + - name: Prepare + run: ci/prepare/macos/prepare.sh + + - name: Build Tests + id: build + run: ci/build-tests.sh + + - name: Core Tests + if: steps.build.outcome == 'success' && (success() || failure()) + continue-on-error: true + run: timeout -sKILL 45m ../ci/tests/run-core-tests.sh + working-directory: build + + - name: RPC Tests + if: steps.build.outcome == 'success' && (success() || failure()) + continue-on-error: true + run: timeout -sKILL 20m ../ci/tests/run-rpc-tests.sh + working-directory: build + + - name: Reports + if: steps.build.outcome == 'success' && (success() || failure()) + continue-on-error: ${{ env.IGNORE_ERRORS == 'true' }} + run: ../ci/tests/show-sanitizer-reports.sh + working-directory: build + diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 83925c80c5..47fb08abf9 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -16,25 +16,13 @@ jobs: BUILD_TYPE: ${{ matrix.RELEASE && 'RelWithDebInfo' || 'Debug' }} TEST_USE_ROCKSDB: ${{ matrix.BACKEND == 'rocksdb' && '1' || '0' }} DEADLINE_SCALE_FACTOR: ${{ matrix.BACKEND == 'rocksdb' && '2' || '1' }} - runs-on: macos-12 + runs-on: macos-14 if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository steps: - name: Checkout uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 0 # Full history needed for restoring file timestamps - - - name: Restore Timestamps - uses: ./.github/actions/restore-git-mtimes - continue-on-error: true - - - name: Restore Build Cache - uses: actions/cache/restore@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-build-cache - name: Prepare run: ci/prepare/macos/prepare.sh @@ -43,15 +31,6 @@ jobs: id: build run: ci/build-tests.sh - - name: Save Build Cache - # Only save build cache from develop to avoid polluting it by other branches / PRs - if: github.ref == 'refs/heads/develop' && success() - uses: actions/cache/save@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-build-cache - - name: Core Tests if: steps.build.outcome == 'success' && (success() || failure()) run: ../ci/tests/run-core-tests.sh @@ -90,18 +69,6 @@ jobs: uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 0 # Full history needed for restoring file timestamps - - - name: Restore Timestamps - uses: ./.github/actions/restore-git-mtimes - continue-on-error: true - - - name: Restore Build Cache - uses: actions/cache/restore@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-${{ env.COMPILER }}-build-cache - name: Prepare run: sudo -E ci/prepare/linux/prepare.sh @@ -110,15 +77,6 @@ jobs: id: build run: ci/build-tests.sh - - name: Save Build Cache - # Only save build cache from develop to avoid polluting it by other branches / PRs - if: github.ref == 'refs/heads/develop' && success() - uses: actions/cache/save@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-${{ env.COMPILER }}-build-cache - - name: Core Tests if: steps.build.outcome == 'success' && (success() || failure()) run: ../ci/tests/run-core-tests.sh @@ -160,18 +118,6 @@ jobs: uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 0 # full history needed for restoring file timestamps - - - name: Restore Timestamps - uses: ./.github/actions/restore-git-mtimes - continue-on-error: true - - - name: Restore Build Cache - uses: actions/cache/restore@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-build-cache - name: Prepare run: ci/prepare/windows/prepare.ps1 @@ -181,15 +127,6 @@ jobs: run: ci/build-tests.sh shell: bash - - name: Save Build Cache - # only save build cache from develop to avoid polluting it by other branches / PRs - if: github.ref == 'refs/heads/develop' && success() - uses: actions/cache/save@v3 - continue-on-error: true - with: - path: build - key: ${{ runner.os }}-build-cache - - name: Core Tests if: steps.build.outcome == 'success' && (success() || failure()) run: ../ci/tests/run-core-tests.sh diff --git a/.gitmodules b/.gitmodules index 6f9e8c84da..c1d9a0bf26 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,9 @@ [submodule "submodules/gtest-parallel"] path = submodules/gtest-parallel url = https://github.com/google/gtest-parallel.git +[submodule "submodules/spdlog"] + path = submodules/spdlog + url = https://github.com/gabime/spdlog.git +[submodule "submodules/fmt"] + path = submodules/fmt + url = https://github.com/fmtlib/fmt.git diff --git a/CL/cl2.hpp b/CL/cl2.hpp index 534c486988..d4f1b51b64 100644 --- a/CL/cl2.hpp +++ b/CL/cl2.hpp @@ -3571,19 +3571,19 @@ cl::pointer>> allocate_svm(const cl } #endif // #if !defined(CL_HPP_NO_STD_UNIQUE_PTR) -/*! \brief Vector alias to simplify contruction of coarse-grained SVM containers. +/*! \brief Vector alias to simplify construction of coarse-grained SVM containers. * */ template < class T > using coarse_svm_vector = vector>>; -/*! \brief Vector alias to simplify contruction of fine-grained SVM containers. +/*! \brief Vector alias to simplify construction of fine-grained SVM containers. * */ template < class T > using fine_svm_vector = vector>>; -/*! \brief Vector alias to simplify contruction of fine-grained SVM containers that support platform atomics. +/*! \brief Vector alias to simplify construction of fine-grained SVM containers that support platform atomics. * */ template < class T > diff --git a/CMakeLists.txt b/CMakeLists.txt index c48e2df2a4..c411cee10e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ endif() # OSX compatibility needs to be set before project is declared set(CMAKE_OSX_DEPLOYMENT_TARGET - 12 + 13.3 CACHE STRING "") project(nano-node) @@ -133,6 +133,17 @@ if(NANO_STACKTRACE_BACKTRACE) endif() endif() +# Enable NANO_TRACING by default in Debug builds +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + option(NANO_TRACING "Enable trace logging" ON) +else() + option(NANO_TRACING "Enable trace logging" OFF) +endif() +if(NANO_TRACING) + message(STATUS "Using trace logging") + add_compile_definitions(NANO_TRACING) +endif() + if(${NANO_TIMED_LOCKS} GREATER 0) add_definitions(-DNANO_TIMED_LOCKS=${NANO_TIMED_LOCKS}) add_definitions(-DNANO_TIMED_LOCKS_FILTER=${NANO_TIMED_LOCKS_FILTER}) @@ -483,10 +494,6 @@ include_directories(${BOOST_LIBRARY_INCLUDES}) add_library(Boost::stacktrace ALIAS boost_stacktrace_basic) add_definitions(-DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) -# Workaround for GitHub builders which do not appear to have the Windows Message -# Compiler mc.exe -add_definitions(-DBOOST_LOG_WITHOUT_EVENT_LOG) - # Workaround for missing reference errata in the boost property_tree module target_link_libraries(boost_property_tree INTERFACE Boost::any) target_link_libraries(boost_property_tree INTERFACE Boost::format) @@ -526,16 +533,27 @@ else() endif() add_subdirectory(submodules/rocksdb EXCLUDE_FROM_ALL) -include_directories(cpptoml/include) +# cpptoml +include_directories(submodules/cpptoml/include) # magic_enum -include_directories(submodules/magic_enum/include) +include_directories(submodules/magic_enum/include/magic_enum) add_subdirectory(crypto/ed25519-donna) add_subdirectory(nano/ipc_flatbuffers_lib) add_subdirectory(nano/ipc_flatbuffers_test) +# fmt +add_subdirectory(submodules/fmt EXCLUDE_FROM_ALL) +include_directories(submodules/fmt/include) + +# spdlog +add_definitions(-DSPDLOG_FMT_EXTERNAL) +add_subdirectory(submodules/spdlog EXCLUDE_FROM_ALL) +include_directories(submodules/spdlog/include) + +# miniupnp set(UPNPC_BUILD_SHARED OFF CACHE BOOL "") @@ -750,6 +768,7 @@ endif() if(NANO_GUI OR RAIBLOCKS_GUI) install(FILES ${PROJECT_BINARY_DIR}/config-node.toml.sample DESTINATION .) install(FILES ${PROJECT_BINARY_DIR}/config-rpc.toml.sample DESTINATION .) + install(FILES ${PROJECT_BINARY_DIR}/config-log.toml.sample DESTINATION .) if(WIN32) set(PLATFORM_QT_PACKAGES WinExtras) else() @@ -760,7 +779,6 @@ if(NANO_GUI OR RAIBLOCKS_GUI) add_library(qt nano/qt/qt.cpp nano/qt/qt.hpp) include_directories(${CMAKE_SOURCE_DIR}/submodules) - include_directories(${CMAKE_SOURCE_DIR}/submodules/cpptoml/include) target_link_libraries( qt diff --git a/boost_checkout_lite.sh b/boost_checkout_lite.sh index 6e650ce7ab..18fe59588f 100755 --- a/boost_checkout_lite.sh +++ b/boost_checkout_lite.sh @@ -9,11 +9,11 @@ git submodule init boost cd boost # deactivate all boost submodules git submodule foreach 'git config submodule.$sm_path.active false' -# selectivly activate required dependencies +# selectively activate required dependencies for i in ${dependencies[@]} do git config submodule.$i.active true done cd .. -# Update all submodules recursivly. Deactivated modules will be skipped by --recursive +# Update all submodules recursively. Deactivated modules will be skipped by --recursive git submodule update --jobs 16 --recursive --recommend-shallow --single-branch diff --git a/ci/build.sh b/ci/build.sh index 7c25a724b5..4aabc4d0fb 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -39,6 +39,9 @@ if [[ ${SANITIZER:-} ]]; then UBSAN) CMAKE_SANITIZER="-DNANO_UBSAN=ON" ;; + LEAK) + CMAKE_SANITIZER="-DNANO_ASAN=ON" + ;; *) echo "Unknown sanitizer: '${SANITIZER}'" exit 1 @@ -57,6 +60,7 @@ cmake \ -DACTIVE_NETWORK=nano_${NANO_NETWORK:-"live"}_network \ -DNANO_TEST=${NANO_TEST:-OFF} \ -DNANO_GUI=${NANO_GUI:-OFF} \ +-DNANO_TRACING=${NANO_TRACING:-OFF} \ -DCOVERAGE=${COVERAGE:-OFF} \ -DCI_TAG=${CI_TAG:-OFF} \ -DCI_VERSION_PRE_RELEASE=${CI_VERSION_PRE_RELEASE:-OFF} \ diff --git a/ci/impl/clang-format.sh b/ci/impl/clang-format.sh index 3a3d69626e..bae7ad070f 100644 --- a/ci/impl/clang-format.sh +++ b/ci/impl/clang-format.sh @@ -3,7 +3,7 @@ ################################################################################################### CLANG_FORMAT="" -CLANG_FORMAT_VERSION="12" +CLANG_FORMAT_VERSION="17" ################################################################################################### diff --git a/ci/impl/code-inspector.sh b/ci/impl/code-inspector.sh index d0f18faed1..0e71cf17f6 100644 --- a/ci/impl/code-inspector.sh +++ b/ci/impl/code-inspector.sh @@ -16,12 +16,6 @@ code_inspect() return 1 fi - # prevent unsolicited use of std::lock_guard, std::unique_lock, std::condition_variable & std::mutex outside of allowed areas - if [[ $(grep -rl --exclude={"*random_pool.cpp","*random_pool.hpp","*random_pool_shuffle.hpp","*locks.hpp","*locks.cpp"} "std::unique_lock\|std::lock_guard\|std::condition_variable\|std::mutex" $SOURCE_ROOT_PATH/nano) ]]; then - echo "Using std::unique_lock, std::lock_guard, std::condition_variable or std::mutex is not permitted (except in nano/lib/locks.hpp and non-nano dependent libraries). Use the nano::* versions instead" >&2 - return 1 - fi - if [[ $(grep -rlP "^\s*assert \(" $SOURCE_ROOT_PATH/nano) ]]; then echo "Using assert is not permitted. Use debug_assert instead." >&2 return 1 diff --git a/ci/tests/run-core-tests.sh b/ci/tests/run-core-tests.sh index a3e02b70bf..31dd324a3f 100755 --- a/ci/tests/run-core-tests.sh +++ b/ci/tests/run-core-tests.sh @@ -1,8 +1,4 @@ #!/bin/bash set -euo pipefail -source "$(dirname "$BASH_SOURCE")/common.sh" - -BUILD_DIR=${1-${PWD}} - -${BUILD_DIR}/core_test$(get_exec_extension) \ No newline at end of file +$(dirname "$BASH_SOURCE")/run-tests.sh core_test \ No newline at end of file diff --git a/ci/tests/run-qt-tests.sh b/ci/tests/run-qt-tests.sh index 8faa28d43a..c53b77544c 100755 --- a/ci/tests/run-qt-tests.sh +++ b/ci/tests/run-qt-tests.sh @@ -1,10 +1,6 @@ #!/bin/bash set -euo pipefail -source "$(dirname "$BASH_SOURCE")/common.sh" - -BUILD_DIR=${1-${PWD}} - # Alpine doesn't offer an xvfb xvfb_run_() { @@ -20,4 +16,4 @@ xvfb_run_() return ${res} } -xvfb_run_ ${BUILD_DIR}/qt_test$(get_exec_extension) \ No newline at end of file +xvfb_run_ $(dirname "$BASH_SOURCE")/run-tests.sh qt_test \ No newline at end of file diff --git a/ci/tests/run-rpc-tests.sh b/ci/tests/run-rpc-tests.sh index 6b64607d95..91dba35e71 100755 --- a/ci/tests/run-rpc-tests.sh +++ b/ci/tests/run-rpc-tests.sh @@ -1,8 +1,4 @@ #!/bin/bash set -euo pipefail -source "$(dirname "$BASH_SOURCE")/common.sh" - -BUILD_DIR=${1-${PWD}} - -${BUILD_DIR}/rpc_test$(get_exec_extension) \ No newline at end of file +$(dirname "$BASH_SOURCE")/run-tests.sh rpc_test \ No newline at end of file diff --git a/ci/tests/run-tests.sh b/ci/tests/run-tests.sh new file mode 100755 index 0000000000..7ac5594e3c --- /dev/null +++ b/ci/tests/run-tests.sh @@ -0,0 +1,64 @@ +#!/bin/bash +set -uo pipefail + +source "$(dirname "$BASH_SOURCE")/common.sh" + +target=$1 +if [ -z "${target-}" ]; then + echo "Target not specified" + exit 1 +fi + +echo "Running tests for target: ${target}" + +# Enable core dumps +DEFAULT_COREDUMP_DIR="/cores" +case "$(uname -s)" in + Linux*) + # Ensure directory exists and is writable for core dumps + sudo mkdir -p "${DEFAULT_COREDUMP_DIR}" + sudo chmod a+w "${DEFAULT_COREDUMP_DIR}" + # Enable core dumps + ulimit -c unlimited + echo "${DEFAULT_COREDUMP_DIR}/core-%e.%p" | sudo tee /proc/sys/kernel/core_pattern + export COREDUMP_DIR=${DEFAULT_COREDUMP_DIR} + + echo "Core dumps enabled (Linux)" + ;; + Darwin*) + # Ensure directory exists and is writable for core dumps + sudo mkdir -p "${DEFAULT_COREDUMP_DIR}" + sudo chmod a+w "${DEFAULT_COREDUMP_DIR}" + # Enable core dumps + ulimit -c unlimited + # By default, macOS writes core dumps to /cores + export COREDUMP_DIR=${DEFAULT_COREDUMP_DIR} + + echo "Core dumps enabled (macOS)" + ;; + CYGWIN*|MINGW32*|MSYS*|MINGW*) + # TODO: Support core dumps on Windows + echo "Core dumps not supported on Windows" + ;; + *) + echo "Unknown OS" + exit 1 + ;; +esac + +# Run the test +executable=./${target}$(get_exec_extension) +"${executable}" +status=$? + +if [ $status -ne 0 ]; then + echo "::error::Test failed: ${target}" + + # Show core dumps + export EXECUTABLE=${executable} + "$(dirname "$BASH_SOURCE")/show-core-dumps.sh" + + exit $status +else + exit 0 +fi \ No newline at end of file diff --git a/ci/tests/show-core-dumps.sh b/ci/tests/show-core-dumps.sh new file mode 100755 index 0000000000..e8409e83a4 --- /dev/null +++ b/ci/tests/show-core-dumps.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -uo pipefail + +echo "Analyzing core dumps..." + +if [ -z "${COREDUMP_DIR-}" ]; then + echo "COREDUMP_DIR environment variable is not set." + exit 1 +fi + +if [ -z "${EXECUTABLE-}" ]; then + echo "EXECUTABLE environment variable is not set." + exit 1 +fi + +echo "Core dump location: ${COREDUMP_DIR}" +echo "Executable: ${EXECUTABLE}" + +analyze_core_dump() { + local core_dump=$1 + local executable=$2 + + case "$(uname)" in + Darwin) + # macOS, use lldb + echo "Using lldb for analysis..." + lldb "${executable}" -c "$core_dump" --batch -o "thread backtrace all" -o "quit" + ;; + Linux) + # Linux, use gdb + echo "Using gdb for analysis..." + gdb -quiet -batch -ex "thread apply all bt full" -ex "quit" "${executable}" "$core_dump" + ;; + *) + echo "Unsupported OS." + return 1 + ;; + esac + + # Remove the analyzed core dump file + echo "Removing analyzed core dump: $core_dump" + rm "$core_dump" +} + +# List core dump files +echo "::group::Core dump files" +ls -al "${COREDUMP_DIR}" +echo "::endgroup::" + +# Use a glob pattern to match core dumps +shopt -s nullglob +core_dumps=("${COREDUMP_DIR}"/core*) + +if [ ${#core_dumps[@]} -gt 0 ]; then + for core_dump in "${core_dumps[@]}"; do + echo "::group::Analyzing core dump: $core_dump" + analyze_core_dump "$core_dump" "${EXECUTABLE}" + echo "::endgroup::" + done +else + echo "No core dump file found." +fi diff --git a/nano/core_test/CMakeLists.txt b/nano/core_test/CMakeLists.txt index 059d15acd1..ba92b42681 100644 --- a/nano/core_test/CMakeLists.txt +++ b/nano/core_test/CMakeLists.txt @@ -22,20 +22,21 @@ add_executable( enums.cpp epochs.cpp frontiers_confirmation.cpp - gap_cache.cpp ipc.cpp ledger.cpp locks.cpp - logger.cpp + logging.cpp message.cpp message_deserializer.cpp memory_pool.cpp network.cpp network_filter.cpp node.cpp + object_stream.cpp optimistic_scheduler.cpp processing_queue.cpp processor_service.cpp + rep_crawler.cpp peer_container.cpp scheduler_buckets.cpp request_aggregator.cpp @@ -64,5 +65,4 @@ target_compile_definitions( target_link_libraries(core_test test_common) include_directories(${CMAKE_SOURCE_DIR}/submodules) -include_directories(${CMAKE_SOURCE_DIR}/submodules/cpptoml/include) include_directories(${CMAKE_SOURCE_DIR}/submodules/gtest/googletest/include) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 3ed7f1f5e7..e40e817015 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -1,9 +1,11 @@ +#include #include #include #include #include #include #include +#include #include #include #include @@ -14,8 +16,6 @@ using namespace std::chrono_literals; -namespace nano -{ /* * Tests that an election can be confirmed as the result of a confirmation request * @@ -39,7 +39,7 @@ TEST (active_transactions, confirm_election_by_request) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Process send1 locally on node1 ASSERT_TRUE (nano::test::process (node1, { send1 })); @@ -80,10 +80,7 @@ TEST (active_transactions, confirm_election_by_request) ASSERT_FALSE (peers.empty ()); // Add representative (node1) to disabled rep crawler of node2 - { - nano::lock_guard guard (node2.rep_crawler.probable_reps_mutex); - node2.rep_crawler.probable_reps.emplace (nano::dev::genesis_key.pub, *peers.cbegin ()); - } + node2.rep_crawler.force_add_rep (nano::dev::genesis_key.pub, *peers.cbegin ()); // Expect a vote to come back ASSERT_TIMELY (5s, election->votes ().size () >= 1); @@ -97,32 +94,12 @@ TEST (active_transactions, confirm_election_by_request) ASSERT_TIMELY (5s, nano::test::confirmed (node1, { send1 })); ASSERT_TIMELY (5s, nano::test::confirmed (node2, { send1 })); } -} -namespace nano -{ TEST (active_transactions, confirm_frontier) { nano::test::system system; - nano::node_flags node_flags; - node_flags.disable_request_loop = true; - // Voting node - auto & node1 = *system.add_node (node_flags); - nano::node_flags node_flags2; - // The rep crawler would otherwise request confirmations in order to find representatives - node_flags2.disable_rep_crawler = true; - auto & node2 = *system.add_node (node_flags2); - - // Add key to node1 - system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - // Add representative to disabled rep crawler - auto peers (node2.network.random_set (1)); - ASSERT_FALSE (peers.empty ()); - { - nano::lock_guard guard (node2.rep_crawler.probable_reps_mutex); - node2.rep_crawler.probable_reps.emplace (nano::dev::genesis_key.pub, *peers.begin ()); - } + // send 100 raw from genesis to a random account nano::state_block_builder builder; auto send = builder .account (nano::dev::genesis_key.pub) @@ -132,21 +109,48 @@ TEST (active_transactions, confirm_frontier) .link (nano::public_key ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - auto send_copy = builder.make_block ().from (*send).build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send).code); - node1.confirmation_height_processor.add (send); - ASSERT_TIMELY (5s, node1.ledger.block_confirmed (node1.store.tx_begin_read (), send->hash ())); - ASSERT_EQ (nano::process_result::progress, node2.process (*send_copy).code); + .build (); + + { + // Voting node + nano::node_flags node_flags; + node_flags.disable_request_loop = true; + node_flags.disable_ongoing_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + auto & node1 = *system.add_node (node_flags); + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + + // we cannot use the same block instance on 2 different nodes, so make a copy + auto send_copy = builder.make_block ().from (*send).build (); + ASSERT_TRUE (nano::test::process (node1, { send_copy })); + ASSERT_TRUE (nano::test::start_elections (system, node1, { send_copy })); + ASSERT_TIMELY (5s, nano::test::confirmed (node1, { send_copy })); + } + + // The rep crawler would otherwise request confirmations in order to find representatives + nano::node_flags node_flags2; + node_flags2.disable_ongoing_bootstrap = true; + node_flags2.disable_ascending_bootstrap = true; + node_flags2.disable_rep_crawler = true; + // start node2 later so that we do not get the gossip traffic + auto & node2 = *system.add_node (node_flags2); + + // Add representative to disabled rep crawler + auto peers (node2.network.random_set (1)); + ASSERT_FALSE (peers.empty ()); + node2.rep_crawler.force_add_rep (nano::dev::genesis_key.pub, *peers.begin ()); + + ASSERT_EQ (nano::block_status::progress, node2.process (send)); ASSERT_TIMELY (5s, !node2.active.empty ()); + // Save election to check request count afterwards - auto election2 = node2.active.election (send->qualified_root ()); - ASSERT_NE (nullptr, election2); + std::shared_ptr election2; + ASSERT_TIMELY (5s, election2 = node2.active.election (send->qualified_root ())); + ASSERT_TIMELY (5s, nano::test::confirmed (node2, { send })); ASSERT_TIMELY_EQ (5s, node2.ledger.cache.cemented_count, 2); ASSERT_TIMELY (5s, node2.active.empty ()); ASSERT_GT (election2->confirmation_request_count, 0u); } -} TEST (active_transactions, keep_local) { @@ -176,6 +180,12 @@ TEST (active_transactions, keep_local) auto const send4 = wallet.send_action (nano::dev::genesis_key.pub, key4.pub, node.config.receive_minimum.number ()); auto const send5 = wallet.send_action (nano::dev::genesis_key.pub, key5.pub, node.config.receive_minimum.number ()); auto const send6 = wallet.send_action (nano::dev::genesis_key.pub, key6.pub, node.config.receive_minimum.number ()); + ASSERT_NE (nullptr, send1); + ASSERT_NE (nullptr, send2); + ASSERT_NE (nullptr, send3); + ASSERT_NE (nullptr, send4); + ASSERT_NE (nullptr, send5); + ASSERT_NE (nullptr, send6); // force-confirm blocks for (auto const & block : { send1, send2, send3, send4, send5, send6 }) @@ -196,7 +206,7 @@ TEST (active_transactions, keep_local) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); const auto receive2 = builder.make_block () .account (key2.pub) .previous (0) @@ -205,7 +215,7 @@ TEST (active_transactions, keep_local) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); + .build (); const auto receive3 = builder.make_block () .account (key3.pub) .previous (0) @@ -214,7 +224,7 @@ TEST (active_transactions, keep_local) .link (send3->hash ()) .sign (key3.prv, key3.pub) .work (*system.work.generate (key3.pub)) - .build_shared (); + .build (); node.process_active (receive1); node.process_active (receive2); node.process_active (receive3); @@ -236,12 +246,11 @@ TEST (active_transactions, inactive_votes_cache) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector (1, send->hash ()))); + .build (); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { send }); node.vote_processor.vote (vote, std::make_shared (node, node)); ASSERT_TIMELY_EQ (5s, node.vote_cache.size (), 1); node.process_active (send); - node.block_processor.flush (); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send->hash ())); ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_cached)); } @@ -260,7 +269,7 @@ TEST (active_transactions, inactive_votes_cache_non_final) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Non-final vote auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector (1, send->hash ())); @@ -290,7 +299,7 @@ TEST (active_transactions, inactive_votes_cache_fork) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (latest) @@ -298,9 +307,9 @@ TEST (active_transactions, inactive_votes_cache_fork) .balance (nano::dev::constants.genesis_amount - 200) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); - auto const vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector (1, send1->hash ())); + auto const vote = nano::test::make_final_vote (nano::dev::genesis_key, { send1 }); node.vote_processor.vote (vote, std::make_shared (node, node)); ASSERT_TIMELY_EQ (5s, node.vote_cache.size (), 1); @@ -330,7 +339,7 @@ TEST (active_transactions, inactive_votes_cache_existing_vote) .balance (nano::dev::constants.genesis_amount - 100 * nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto open = builder.state () .account (key.pub) .previous (0) @@ -339,16 +348,15 @@ TEST (active_transactions, inactive_votes_cache_existing_vote) .link (send->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); node.process_active (send); node.block_processor.add (open); - node.block_processor.flush (); ASSERT_TIMELY_EQ (5s, node.active.size (), 1); auto election (node.active.election (send->qualified_root ())); ASSERT_NE (nullptr, election); ASSERT_GT (node.weight (key.pub), node.minimum_principal_weight ()); // Insert vote - auto vote1 (std::make_shared (key.pub, key.prv, nano::vote::timestamp_min * 1, 0, std::vector (1, send->hash ()))); + auto vote1 = nano::test::make_vote (key, { send }, nano::vote::timestamp_min * 1, 0); node.vote_processor.vote (vote1, std::make_shared (node, node)); ASSERT_TIMELY_EQ (5s, election->votes ().size (), 2); ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_new)); @@ -386,7 +394,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes) .balance (nano::dev::constants.genesis_amount - 100 * nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.send () .previous (send1->hash ()) @@ -394,7 +402,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes) .balance (100 * nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); auto open = builder.state () .account (key1.pub) @@ -404,17 +412,17 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); // put the blocks in the ledger witout triggering an election ASSERT_TRUE (nano::test::process (node, { send1, send2, open })); ASSERT_TIMELY (5s, nano::test::exists (node, { send1, send2, open })); // Process votes - auto vote1 (std::make_shared (key1.pub, key1.prv, 0, 0, std::vector (1, send1->hash ()))); + auto vote1 = nano::test::make_vote (key1, { send1 }, 0, 0); node.vote_processor.vote (vote1, std::make_shared (node, node)); - auto vote2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector (1, send1->hash ()))); + auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, 0, 0); node.vote_processor.vote (vote2, std::make_shared (node, node)); ASSERT_TIMELY (5s, node.vote_cache.find (send1->hash ())); @@ -446,14 +454,14 @@ TEST (active_transactions, inactive_votes_cache_election_start) .balance (nano::dev::constants.genesis_amount - amount) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto send2 = send_block_builder.make_block () .previous (send1->hash ()) .destination (key2.pub) .balance (nano::dev::constants.genesis_amount - 2 * amount) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); auto open1 = state_block_builder.make_block () .account (key1.pub) .previous (0) @@ -462,7 +470,7 @@ TEST (active_transactions, inactive_votes_cache_election_start) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); auto open2 = state_block_builder.make_block () .account (key2.pub) .previous (0) @@ -471,11 +479,11 @@ TEST (active_transactions, inactive_votes_cache_election_start) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*open1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*open2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send1)); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); + ASSERT_EQ (nano::block_status::progress, node.process (open1)); + ASSERT_EQ (nano::block_status::progress, node.process (open2)); ASSERT_TIMELY_EQ (5s, 5, node.ledger.cache.block_count); ASSERT_TRUE (node.active.empty ()); ASSERT_EQ (1, node.ledger.cache.cemented_count); @@ -483,17 +491,17 @@ TEST (active_transactions, inactive_votes_cache_election_start) auto send3 = send_block_builder.make_block () .previous (send2->hash ()) .destination (nano::keypair ().pub) - .balance (send2->balance ().number () - 1) + .balance (send2->balance_field ().value ().number () - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send2->hash ())) - .build_shared (); + .build (); auto send4 = send_block_builder.make_block () .previous (send3->hash ()) .destination (nano::keypair ().pub) - .balance (send3->balance ().number () - 1) + .balance (send3->balance_field ().value ().number () - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send3->hash ())) - .build_shared (); + .build (); // Inactive votes auto vote1 = nano::test::make_vote (key1, { open1, open2, send4 }); @@ -541,6 +549,8 @@ TEST (active_transactions, vote_replays) auto & node = *system.add_node (node_config); nano::keypair key; nano::state_block_builder builder; + + // send Gxrb_ratio raw from genesis to key auto send1 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -549,8 +559,10 @@ TEST (active_transactions, vote_replays) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); ASSERT_NE (nullptr, send1); + + // create open block for key receing Gxrb_ratio raw auto open1 = builder.make_block () .account (key.pub) .previous (0) @@ -559,28 +571,33 @@ TEST (active_transactions, vote_replays) .link (send1->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); ASSERT_NE (nullptr, open1); + + // wait for elections objects to appear in the AEC node.process_active (send1); node.process_active (open1); ASSERT_TRUE (nano::test::start_elections (system, node, { send1, open1 })); ASSERT_EQ (2, node.active.size ()); + // First vote is not a replay and confirms the election, second vote should be a replay since the election has confirmed but not yet removed - auto vote_send1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ send1->hash () })); + auto vote_send1 = nano::test::make_final_vote (nano::dev::genesis_key, { send1 }); ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote_send1)); - ASSERT_EQ (2, node.active.size ()); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote_send1)); + // Wait until the election is removed, at which point the vote is still a replay since it's been recently confirmed - ASSERT_TIMELY_EQ (3s, node.active.size (), 1); + ASSERT_TIMELY_EQ (5s, node.active.size (), 1); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote_send1)); + // Open new account - auto vote_open1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ open1->hash () })); + auto vote_open1 = nano::test::make_final_vote (nano::dev::genesis_key, { open1 }); ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote_open1)); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote_open1)); - ASSERT_TIMELY (3s, node.active.empty ()); + ASSERT_TIMELY (5s, node.active.empty ()); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote_open1)); ASSERT_EQ (nano::Gxrb_ratio, node.ledger.weight (key.pub)); + // send 1 raw to key to key auto send2 = builder.make_block () .account (key.pub) .previous (open1->hash ()) @@ -589,22 +606,24 @@ TEST (active_transactions, vote_replays) .link (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (open1->hash ())) - .build_shared (); + .build (); ASSERT_NE (nullptr, send2); node.process_active (send2); ASSERT_TRUE (nano::test::start_elections (system, node, { send2 })); ASSERT_EQ (1, node.active.size ()); - auto vote1_send2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ send2->hash () })); - auto vote2_send2 (std::make_shared (key.pub, key.prv, 0, 0, std::vector{ send2->hash () })); - ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote2_send2)); - ASSERT_EQ (1, node.active.size ()); - ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote2_send2)); + + // vote2_send2 is a non final vote with little weight, vote1_send2 is the vote that confirms the election + auto vote1_send2 = nano::test::make_final_vote (nano::dev::genesis_key, { send2 }); + auto vote2_send2 = nano::test::make_vote (key, { send2 }, 0, 0); + ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote2_send2)); // this vote cannot confirm the election ASSERT_EQ (1, node.active.size ()); - ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote1_send2)); + ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote2_send2)); // this vote cannot confirm the election ASSERT_EQ (1, node.active.size ()); + ASSERT_EQ (nano::vote_code::vote, node.active.vote (vote1_send2)); // this vote confirms the election + + // this should still return replay, either because the election is still in the AEC or because it is recently confirmed ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote1_send2)); - ASSERT_TIMELY (3s, node.active.empty ()); - ASSERT_EQ (0, node.active.size ()); + ASSERT_TIMELY (5s, node.active.empty ()); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote1_send2)); ASSERT_EQ (nano::vote_code::replay, node.active.vote (vote2_send2)); @@ -697,10 +716,10 @@ TEST (active_transactions, republish_winner) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send1); - node1.block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (node1, { send1 })); ASSERT_TIMELY_EQ (3s, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in), 1); // Several forks @@ -714,10 +733,10 @@ TEST (active_transactions, republish_winner) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (fork); + ASSERT_TIMELY (5s, node1.active.active (*fork)); } - node1.block_processor.flush (); ASSERT_TIMELY (3s, !node1.active.empty ()); ASSERT_EQ (1, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in)); @@ -730,16 +749,15 @@ TEST (active_transactions, republish_winner) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (fork); - node1.block_processor.flush (); + ASSERT_TIMELY (5s, node1.active.active (fork->hash ())); auto election = node1.active.election (fork->qualified_root ()); ASSERT_NE (nullptr, election); - auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ fork->hash () }); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { fork }); node1.vote_processor.vote (vote, std::make_shared (node1, node1)); node1.vote_processor.flush (); - node1.block_processor.flush (); ASSERT_TIMELY (5s, election->confirmed ()); ASSERT_EQ (fork->hash (), election->status.winner->hash ()); ASSERT_TIMELY (5s, node2.block_confirmed (fork->hash ())); @@ -765,7 +783,7 @@ TEST (active_transactions, fork_filter_cleanup) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); std::vector send_block_bytes{}; { @@ -784,7 +802,7 @@ TEST (active_transactions, fork_filter_cleanup) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (fork); ASSERT_TIMELY (5s, node1.active.election (fork->qualified_root ()) != nullptr); @@ -854,7 +872,7 @@ TEST (active_transactions, fork_replacement_tally) .link (keys[i].pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); node1.process_active (send); latest = send->hash (); auto open = builder.make_block () @@ -865,10 +883,10 @@ TEST (active_transactions, fork_replacement_tally) .link (send->hash ()) .sign (keys[i].prv, keys[i].pub) .work (*system.work.generate (keys[i].pub)) - .build_shared (); + .build (); node1.process_active (open); // Confirmation - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ send->hash (), open->hash () })); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { send, open }); node1.vote_processor.vote (vote, std::make_shared (node1, node1)); } ASSERT_TIMELY_EQ (5s, node1.ledger.cache.cemented_count, 1 + 2 * reps_count); @@ -882,7 +900,7 @@ TEST (active_transactions, fork_replacement_tally) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); // Forks without votes for (auto i (0); i < reps_count; i++) @@ -895,14 +913,13 @@ TEST (active_transactions, fork_replacement_tally) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); node1.process_active (fork); } - ASSERT_TIMELY (5s, !node1.active.empty ()); // Check overflow of blocks - auto election = node1.active.election (send_last->qualified_root ()); - ASSERT_NE (nullptr, election); + std::shared_ptr election; + ASSERT_TIMELY (5s, election = node1.active.election (send_last->qualified_root ())); ASSERT_TIMELY_EQ (5s, max_blocks, election->blocks ().size ()); // Generate forks with votes to prevent new block insertion to election @@ -916,8 +933,8 @@ TEST (active_transactions, fork_replacement_tally) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); - auto vote (std::make_shared (keys[i].pub, keys[i].prv, 0, 0, std::vector{ fork->hash () })); + .build (); + auto vote = nano::test::make_vote (keys[i], { fork }, 0, 0); node1.vote_processor.vote (vote, std::make_shared (node1, node1)); node1.vote_processor.flush (); node1.process_active (fork); @@ -953,16 +970,14 @@ TEST (active_transactions, fork_replacement_tally) node1.network.publish_filter.clear (); node2.network.flood_block (send_last); ASSERT_TIMELY (3s, node1.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in) > 0); - node1.block_processor.flush (); - system.delay_ms (50ms); // Correct block without votes is ignored - auto blocks1 (election->blocks ()); - ASSERT_EQ (max_blocks, blocks1.size ()); + std::unordered_map> blocks1; + ASSERT_TIMELY_EQ (5s, max_blocks, (blocks1 = election->blocks (), blocks1.size ())); ASSERT_FALSE (blocks1.find (send_last->hash ()) != blocks1.end ()); // Process vote for correct block & replace existing lowest tally block - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ send_last->hash () })); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { send_last }, 0, 0); node1.vote_processor.vote (vote, std::make_shared (node1, node1)); node1.vote_processor.flush (); // ensure vote arrives before the block @@ -1016,10 +1031,7 @@ TEST (active_transactions, confirmation_consistency) } } -// Test disabled because it's failing intermittently. -// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3629 -// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3634 -TEST (active_transactions, DISABLED_confirm_new) +TEST (active_transactions, confirm_new) { nano::test::system system (1); auto & node1 = *system.nodes[0]; @@ -1029,9 +1041,8 @@ TEST (active_transactions, DISABLED_confirm_new) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send); - node1.block_processor.flush (); ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); auto & node2 = *system.add_node (); // Add key to node2 @@ -1039,7 +1050,8 @@ TEST (active_transactions, DISABLED_confirm_new) // Let node2 know about the block ASSERT_TIMELY (5s, node2.block (send->hash ())); // Wait confirmation - ASSERT_TIMELY (5s, node1.ledger.cache.cemented_count == 2 && node2.ledger.cache.cemented_count == 2); + ASSERT_TIMELY (5s, node1.ledger.cache.cemented_count == 2); + ASSERT_TIMELY (5s, node2.ledger.cache.cemented_count == 2); } // Ensures votes are tallied on election::publish even if no vote is inserted through inactive_votes_cache @@ -1059,7 +1071,7 @@ TEST (active_transactions, conflicting_block_vote_existing_election) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto fork = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -1068,17 +1080,17 @@ TEST (active_transactions, conflicting_block_vote_existing_election) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - auto vote_fork (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ fork->hash () })); + .build (); + auto vote_fork = nano::test::make_final_vote (nano::dev::genesis_key, { fork }); - ASSERT_EQ (nano::process_result::progress, node.process_local (send).value ().code); + ASSERT_EQ (nano::block_status::progress, node.process_local (send).value ()); ASSERT_TIMELY_EQ (5s, 1, node.active.size ()); // Vote for conflicting block, but the block does not yet exist in the ledger node.active.vote (vote_fork); // Block now gets processed - ASSERT_EQ (nano::process_result::fork, node.process_local (fork).value ().code); + ASSERT_EQ (nano::block_status::fork, node.process_local (fork).value ()); // Election must be confirmed auto election (node.active.election (fork->qualified_root ())); @@ -1141,11 +1153,11 @@ TEST (active_transactions, activate_account_chain) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*send3).code); - ASSERT_EQ (nano::process_result::progress, node.process (*open).code); - ASSERT_EQ (nano::process_result::progress, node.process (*receive).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); + ASSERT_EQ (nano::block_status::progress, node.process (send3)); + ASSERT_EQ (nano::block_status::progress, node.process (open)); + ASSERT_EQ (nano::block_status::progress, node.process (receive)); node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); ASSERT_TIMELY (5s, node.active.election (send->qualified_root ())); @@ -1204,7 +1216,7 @@ TEST (active_transactions, activate_inactive) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send->hash ()) @@ -1213,7 +1225,7 @@ TEST (active_transactions, activate_inactive) .balance (nano::dev::constants.genesis_amount - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); auto open = builder.make_block () .account (key.pub) .previous (0) @@ -1222,11 +1234,11 @@ TEST (active_transactions, activate_inactive) .balance (1) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*open).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); + ASSERT_EQ (nano::block_status::progress, node.process (open)); auto election = nano::test::start_election (system, node, send2->hash ()); ASSERT_NE (nullptr, election); @@ -1259,9 +1271,9 @@ TEST (active_transactions, list_active) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -1271,9 +1283,9 @@ TEST (active_transactions, list_active) .balance (nano::dev::constants.genesis_amount - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); auto open = builder.make_block () .account (key.pub) @@ -1283,9 +1295,9 @@ TEST (active_transactions, list_active) .balance (1) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*open).code); + ASSERT_EQ (nano::block_status::progress, node.process (open)); ASSERT_TRUE (nano::test::start_elections (system, node, { send, send2, open })); ASSERT_EQ (3, node.active.size ()); @@ -1316,9 +1328,9 @@ TEST (active_transactions, vacancy) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node.active.vacancy_update = [&updated] () { updated = true; }; - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); ASSERT_EQ (1, node.active.vacancy ()); ASSERT_EQ (0, node.active.size ()); node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); @@ -1342,6 +1354,7 @@ TEST (active_transactions, fifo) nano::node_config config = system.default_config (); config.active_elections_size = 1; + config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node = *system.add_node (config); auto latest_hash = nano::dev::genesis->hash (); @@ -1357,8 +1370,8 @@ TEST (active_transactions, fifo) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send1)); node.process_confirmed (nano::election_status{ send1 }); ASSERT_TIMELY (5s, node.block_confirmed (send1->hash ())); @@ -1372,8 +1385,8 @@ TEST (active_transactions, fifo) .balance (nano::dev::constants.genesis_amount - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); node.process_confirmed (nano::election_status{ send2 }); ASSERT_TIMELY (5s, node.block_confirmed (send2->hash ())); @@ -1385,8 +1398,8 @@ TEST (active_transactions, fifo) .balance (1) .sign (key0.prv, key0.pub) .work (*system.work.generate (key0.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (receive1)); auto receive2 = builder.make_block () .previous (0) @@ -1396,8 +1409,8 @@ TEST (active_transactions, fifo) .balance (1) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*receive2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (receive2)); // Ensure first transaction becomes active node.scheduler.manual.push (receive1); diff --git a/nano/core_test/backlog.cpp b/nano/core_test/backlog.cpp index facbf0b538..26d5680a88 100644 --- a/nano/core_test/backlog.cpp +++ b/nano/core_test/backlog.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -32,9 +33,7 @@ TEST (backlog, population) auto all_activated = [&] () { nano::lock_guard lock{ mutex }; return std::all_of (blocks.begin (), blocks.end (), [&] (auto const & item) { - auto account = item->account (); - debug_assert (!account.is_zero ()); - return activated.count (account) != 0; + return activated.count (item->account ()) != 0; }); }; ASSERT_TIMELY (5s, all_activated ()); diff --git a/nano/core_test/block.cpp b/nano/core_test/block.cpp index 7a2c37b812..f5dd614b3d 100644 --- a/nano/core_test/block.cpp +++ b/nano/core_test/block.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -385,7 +386,7 @@ TEST (block, publish_req_serialization) .balance (200) .sign (nano::keypair ().prv, 2) .work (3) - .build_shared (); + .build (); nano::publish req{ nano::dev::network_params.network, block }; std::vector bytes; { @@ -429,7 +430,7 @@ TEST (state_block, serialization) .link (4) .sign (key1.prv, key1.pub) .work (5) - .build_shared (); + .build (); ASSERT_EQ (key1.pub, block1->hashables.account); ASSERT_EQ (nano::block_hash (1), block1->previous ()); ASSERT_EQ (key2.pub, block1->hashables.representative); @@ -489,7 +490,7 @@ TEST (state_block, hashing) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); auto hash (block->hash ()); ASSERT_EQ (hash, block->hash ()); // check cache works block->hashables.account.bytes[0] ^= 0x1; @@ -551,7 +552,7 @@ TEST (block_uniquer, single) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); auto block2 (std::make_shared (*block1)); ASSERT_NE (block1, block2); ASSERT_EQ (*block1, *block2); @@ -578,7 +579,7 @@ TEST (block_uniquer, cleanup) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); auto block2 = builder .make_block () .account (0) @@ -588,7 +589,7 @@ TEST (block_uniquer, cleanup) .link (0) .sign (key.prv, key.pub) .work (1) - .build_shared (); + .build (); nano::block_uniquer uniquer; auto block3 = uniquer.unique (block1); @@ -636,7 +637,7 @@ TEST (block_builder, zeroed_state_block) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); auto zero_block_build = builder.state ().zero ().sign (key.prv, key.pub).build (); ASSERT_EQ (zero_block_manual->hash (), zero_block_build->hash ()); ASSERT_FALSE (nano::validate_message (key.pub, zero_block_build->hash (), zero_block_build->signature)); @@ -656,9 +657,9 @@ TEST (block_builder, state) .link_hex ("E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86") .build (ec); ASSERT_EQ (block->hash ().to_string (), "2D243F8F92CDD0AD94A1D456A6B15F3BE7A6FCBD98D4C5831D06D15C818CD81F"); - ASSERT_TRUE (block->source ().is_zero ()); - ASSERT_TRUE (block->destination ().is_zero ()); - ASSERT_EQ (block->link ().to_string (), "E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86"); + ASSERT_FALSE (block->source_field ()); + ASSERT_FALSE (block->destination_field ()); + ASSERT_EQ (block->link_field ().value ().to_string (), "E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86"); } TEST (block_builder, state_missing_rep) @@ -729,9 +730,9 @@ TEST (block_builder, open) .source_hex ("E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA") .build (ec); ASSERT_EQ (block->hash ().to_string (), "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948"); - ASSERT_EQ (block->source ().to_string (), "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA"); - ASSERT_TRUE (block->destination ().is_zero ()); - ASSERT_TRUE (block->link ().is_zero ()); + ASSERT_EQ (block->source_field ().value ().to_string (), "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA"); + ASSERT_FALSE (block->destination_field ()); + ASSERT_FALSE (block->link_field ()); } TEST (block_builder, open_equality) @@ -768,9 +769,9 @@ TEST (block_builder, change) .previous_hex ("088EE46429CA936F76C4EAA20B97F6D33E5D872971433EE0C1311BCB98764456") .build (ec); ASSERT_EQ (block->hash ().to_string (), "13552AC3928E93B5C6C215F61879358E248D4A5246B8B3D1EEC5A566EDCEE077"); - ASSERT_TRUE (block->source ().is_zero ()); - ASSERT_TRUE (block->destination ().is_zero ()); - ASSERT_TRUE (block->link ().is_zero ()); + ASSERT_FALSE (block->source_field ()); + ASSERT_FALSE (block->destination_field ()); + ASSERT_FALSE (block->link_field ()); } TEST (block_builder, change_equality) @@ -807,9 +808,9 @@ TEST (block_builder, send) .balance_hex ("00F035A9C7D818E7C34148C524FFFFEE") .build (ec); ASSERT_EQ (block->hash ().to_string (), "4560E7B1F3735D082700CFC2852F5D1F378F7418FD24CEF1AD45AB69316F15CD"); - ASSERT_TRUE (block->source ().is_zero ()); - ASSERT_EQ (block->destination ().to_account (), "nano_1gys8r4crpxhp94n4uho5cshaho81na6454qni5gu9n53gksoyy1wcd4udyb"); - ASSERT_TRUE (block->link ().is_zero ()); + ASSERT_FALSE (block->source_field ()); + ASSERT_EQ (block->destination_field ().value ().to_account (), "nano_1gys8r4crpxhp94n4uho5cshaho81na6454qni5gu9n53gksoyy1wcd4udyb"); + ASSERT_FALSE (block->link_field ()); } TEST (block_builder, send_equality) @@ -869,7 +870,7 @@ TEST (block_builder, receive) .source_hex ("7B2B0A29C1B235FDF9B4DEF2984BB3573BD1A52D28246396FBB3E4C5FE662135") .build (ec); ASSERT_EQ (block->hash ().to_string (), "6C004BF911D9CF2ED75CF6EC45E795122AD5D093FF5A83EDFBA43EC4A3EDC722"); - ASSERT_EQ (block->source ().to_string (), "7B2B0A29C1B235FDF9B4DEF2984BB3573BD1A52D28246396FBB3E4C5FE662135"); - ASSERT_TRUE (block->destination ().is_zero ()); - ASSERT_TRUE (block->link ().is_zero ()); + ASSERT_EQ (block->source_field ().value ().to_string (), "7B2B0A29C1B235FDF9B4DEF2984BB3573BD1A52D28246396FBB3E4C5FE662135"); + ASSERT_FALSE (block->destination_field ()); + ASSERT_FALSE (block->link_field ()); } diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 59c8092450..07ca6d9b08 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -1,6 +1,7 @@ #include +#include #include -#include +#include #include #include #include @@ -27,7 +28,7 @@ using namespace std::chrono_literals; TEST (block_store, construction) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); } @@ -102,7 +103,7 @@ TEST (block_store, sideband_serialization) TEST (block_store, add_item) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -133,7 +134,7 @@ TEST (block_store, add_item) TEST (block_store, clear_successor) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -180,7 +181,7 @@ TEST (block_store, clear_successor) TEST (block_store, add_nonempty_block) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::keypair key1; @@ -207,7 +208,7 @@ TEST (block_store, add_nonempty_block) TEST (block_store, add_two_items) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::keypair key1; @@ -253,7 +254,7 @@ TEST (block_store, add_two_items) TEST (block_store, add_receive) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::keypair key1; @@ -289,25 +290,25 @@ TEST (block_store, add_receive) TEST (block_store, add_pending) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::keypair key1; nano::pending_key key2 (0, 0); - nano::pending_info pending1; auto transaction (store->tx_begin_write ()); - ASSERT_TRUE (store->pending.get (transaction, key2, pending1)); + ASSERT_FALSE (store->pending.get (transaction, key2)); + nano::pending_info pending1; store->pending.put (transaction, key2, pending1); - nano::pending_info pending2; - ASSERT_FALSE (store->pending.get (transaction, key2, pending2)); + std::optional pending2; + ASSERT_TRUE (pending2 = store->pending.get (transaction, key2)); ASSERT_EQ (pending1, pending2); store->pending.del (transaction, key2); - ASSERT_TRUE (store->pending.get (transaction, key2, pending2)); + ASSERT_FALSE (store->pending.get (transaction, key2)); } TEST (block_store, pending_iterator) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); auto transaction (store->tx_begin_write ()); @@ -332,7 +333,7 @@ TEST (block_store, pending_iterator) */ TEST (block_store, pending_iterator_comparison) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -375,14 +376,14 @@ TEST (block_store, pending_iterator_comparison) TEST (block_store, genesis) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::ledger_cache ledger_cache; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); nano::account_info info; - ASSERT_FALSE (store->account.get (transaction, nano::dev::genesis->account (), info)); + ASSERT_FALSE (store->account.get (transaction, nano::dev::genesis_key.pub, info)); ASSERT_EQ (nano::dev::genesis->hash (), info.head); auto block1 (store->block.get (transaction, info.head)); ASSERT_NE (nullptr, block1); @@ -392,18 +393,18 @@ TEST (block_store, genesis) ASSERT_EQ (info.block_count, 1); // Genesis block should be confirmed by default nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store->confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE (store->confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (confirmation_height_info.height, 1); ASSERT_EQ (confirmation_height_info.frontier, nano::dev::genesis->hash ()); auto dev_pub_text (nano::dev::genesis_key.pub.to_string ()); auto dev_pub_account (nano::dev::genesis_key.pub.to_account ()); auto dev_prv_text (nano::dev::genesis_key.prv.to_string ()); - ASSERT_EQ (nano::dev::genesis->account (), nano::dev::genesis_key.pub); + ASSERT_EQ (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub); } TEST (block_store, empty_accounts) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); auto transaction (store->tx_begin_read ()); @@ -414,7 +415,7 @@ TEST (block_store, empty_accounts) TEST (block_store, one_block) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -435,8 +436,9 @@ TEST (block_store, one_block) TEST (block_store, empty_bootstrap) { nano::test::system system{}; - nano::logger_mt logger; - nano::unchecked_map unchecked{ system.stats, false }; + nano::logger logger; + unsigned max_unchecked_blocks = 65536; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; size_t count = 0; unchecked.for_each ([&count] (nano::unchecked_key const & key, nano::unchecked_info const & info) { ++count; @@ -446,7 +448,7 @@ TEST (block_store, empty_bootstrap) TEST (block_store, unchecked_begin_search) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::keypair key0; @@ -471,7 +473,7 @@ TEST (block_store, unchecked_begin_search) TEST (block_store, frontier_retrieval) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::account account1{}; @@ -486,7 +488,7 @@ TEST (block_store, frontier_retrieval) TEST (block_store, one_account) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::account account{}; @@ -513,7 +515,7 @@ TEST (block_store, one_account) TEST (block_store, two_block) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -551,7 +553,7 @@ TEST (block_store, two_block) TEST (block_store, two_account) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::account account1 (1); @@ -593,7 +595,7 @@ TEST (block_store, two_account) TEST (block_store, latest_find) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::account account1 (1); @@ -627,7 +629,7 @@ TEST (mdb_block_store, supported_version_upgrades) } // Check that upgrading from an unsupported version is not supported auto path (nano::unique_path () / "data.ldb"); - nano::logger_mt logger; + nano::logger logger; { nano::store::lmdb::component store (logger, path, nano::dev::constants); nano::stats stats; @@ -671,10 +673,11 @@ TEST (mdb_block_store, bad_path) // Don't test this in rocksdb mode GTEST_SKIP (); } - nano::logger_mt logger; + nano::logger logger; try { auto path = nano::unique_path (); + path /= "data.ldb"; { std::ofstream stream (path.c_str ()); } @@ -696,14 +699,14 @@ TEST (block_store, DISABLED_already_open) // File can be shared std::ofstream file; file.open (path.string ().c_str ()); ASSERT_TRUE (file.is_open ()); - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (store->init_error ()); } TEST (block_store, roots) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -745,7 +748,7 @@ TEST (block_store, roots) TEST (block_store, pending_exists) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::pending_key two (2, 0); @@ -758,7 +761,7 @@ TEST (block_store, pending_exists) TEST (block_store, latest_exists) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::account two (2); @@ -772,7 +775,7 @@ TEST (block_store, latest_exists) TEST (block_store, large_iteration) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); std::unordered_set accounts1; @@ -811,7 +814,7 @@ TEST (block_store, large_iteration) TEST (block_store, frontier) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); auto transaction (store->tx_begin_write ()); @@ -826,7 +829,7 @@ TEST (block_store, frontier) TEST (block_store, block_replace) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -858,7 +861,7 @@ TEST (block_store, block_replace) TEST (block_store, block_count) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); { @@ -883,7 +886,7 @@ TEST (block_store, block_count) TEST (block_store, account_count) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); { @@ -899,7 +902,7 @@ TEST (block_store, account_count) TEST (block_store, cemented_count_cache) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); auto transaction (store->tx_begin_write ()); @@ -910,7 +913,7 @@ TEST (block_store, cemented_count_cache) TEST (block_store, block_random) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); { nano::ledger_cache ledger_cache; @@ -925,7 +928,7 @@ TEST (block_store, block_random) TEST (block_store, pruned_random) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -952,7 +955,7 @@ TEST (block_store, pruned_random) TEST (block_store, state_block) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::keypair key1; @@ -999,7 +1002,7 @@ TEST (mdb_block_store, sideband_height) // Don't test this in rocksdb mode GTEST_SKIP (); } - nano::logger_mt logger; + nano::logger logger; nano::keypair key1; nano::keypair key2; nano::keypair key3; @@ -1019,7 +1022,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto receive = builder .receive () .previous (send->hash ()) @@ -1027,7 +1030,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); auto change = builder .change () .previous (receive->hash ()) @@ -1035,7 +1038,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (receive->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change)); auto state_send1 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1046,7 +1049,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (change->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *state_send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, state_send1)); auto state_send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1057,7 +1060,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (state_send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *state_send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, state_send2)); auto state_send3 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1068,7 +1071,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (state_send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *state_send3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, state_send3)); auto state_open = builder .state () .account (key1.pub) @@ -1079,7 +1082,7 @@ TEST (mdb_block_store, sideband_height) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *state_open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, state_open)); auto epoch = builder .state () .account (key1.pub) @@ -1090,7 +1093,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (state_open->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch)); ASSERT_EQ (nano::epoch::epoch_1, ledger.version (*epoch)); auto epoch_open = builder .state () @@ -1102,7 +1105,7 @@ TEST (mdb_block_store, sideband_height) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch_open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch_open)); ASSERT_EQ (nano::epoch::epoch_1, ledger.version (*epoch_open)); auto state_receive = builder .state () @@ -1114,7 +1117,7 @@ TEST (mdb_block_store, sideband_height) .sign (key2.prv, key2.pub) .work (*pool.generate (epoch_open->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *state_receive).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, state_receive)); auto open = builder .open () .source (state_send3->hash ()) @@ -1123,36 +1126,36 @@ TEST (mdb_block_store, sideband_height) .sign (key3.prv, key3.pub) .work (*pool.generate (key3.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); - auto block1 (store.block.get (transaction, nano::dev::genesis->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); + auto block1 = ledger.block (transaction, nano::dev::genesis->hash ()); ASSERT_EQ (block1->sideband ().height, 1); - auto block2 (store.block.get (transaction, send->hash ())); + auto block2 = ledger.block (transaction, send->hash ()); ASSERT_EQ (block2->sideband ().height, 2); - auto block3 (store.block.get (transaction, receive->hash ())); + auto block3 = ledger.block (transaction, receive->hash ()); ASSERT_EQ (block3->sideband ().height, 3); - auto block4 (store.block.get (transaction, change->hash ())); + auto block4 = ledger.block (transaction, change->hash ()); ASSERT_EQ (block4->sideband ().height, 4); - auto block5 (store.block.get (transaction, state_send1->hash ())); + auto block5 = ledger.block (transaction, state_send1->hash ()); ASSERT_EQ (block5->sideband ().height, 5); - auto block6 (store.block.get (transaction, state_send2->hash ())); + auto block6 = ledger.block (transaction, state_send2->hash ()); ASSERT_EQ (block6->sideband ().height, 6); - auto block7 (store.block.get (transaction, state_send3->hash ())); + auto block7 = ledger.block (transaction, state_send3->hash ()); ASSERT_EQ (block7->sideband ().height, 7); - auto block8 (store.block.get (transaction, state_open->hash ())); + auto block8 = ledger.block (transaction, state_open->hash ()); ASSERT_EQ (block8->sideband ().height, 1); - auto block9 (store.block.get (transaction, epoch->hash ())); + auto block9 = ledger.block (transaction, epoch->hash ()); ASSERT_EQ (block9->sideband ().height, 2); - auto block10 (store.block.get (transaction, epoch_open->hash ())); + auto block10 = ledger.block (transaction, epoch_open->hash ()); ASSERT_EQ (block10->sideband ().height, 1); - auto block11 (store.block.get (transaction, state_receive->hash ())); + auto block11 = ledger.block (transaction, state_receive->hash ()); ASSERT_EQ (block11->sideband ().height, 2); - auto block12 (store.block.get (transaction, open->hash ())); + auto block12 = ledger.block (transaction, open->hash ()); ASSERT_EQ (block12->sideband ().height, 1); } TEST (block_store, peers) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1250,7 +1253,7 @@ TEST (block_store, endpoint_key_byte_order) TEST (block_store, online_weight) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); { @@ -1285,7 +1288,7 @@ TEST (block_store, online_weight) TEST (block_store, pruned_blocks) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1372,7 +1375,7 @@ TEST (mdb_block_store, upgrade_v21_v22) } auto path (nano::unique_path () / "data.ldb"); - nano::logger_mt logger; + nano::logger logger; nano::stats stats; auto const check_correct_state = [&] () { nano::store::lmdb::component store (logger, path, nano::dev::constants); @@ -1411,7 +1414,7 @@ TEST (rocksdb_block_store, upgrade_v21_v22) } auto const path = nano::unique_path () / "rocksdb"; - nano::logger_mt logger; + nano::logger logger; nano::stats stats; auto const check_correct_state = [&] () { nano::store::rocksdb::component store (logger, path, nano::dev::constants); @@ -1471,7 +1474,7 @@ TEST (mdb_block_store, upgrade_backup) }; { - nano::logger_mt logger; + nano::logger logger; nano::store::lmdb::component store (logger, path, nano::dev::constants); auto transaction (store.tx_begin_write ()); store.version.put (transaction, store.version_minimum); @@ -1479,7 +1482,7 @@ TEST (mdb_block_store, upgrade_backup) ASSERT_EQ (get_backup_path ().string (), dir.string ()); // Now do the upgrade and confirm that backup is saved - nano::logger_mt logger; + nano::logger logger; nano::store::lmdb::component store (logger, path, nano::dev::constants, nano::txn_tracking_config{}, std::chrono::seconds (5), nano::lmdb_config{}, true); ASSERT_FALSE (store.init_error ()); auto transaction (store.tx_begin_read ()); @@ -1496,7 +1499,7 @@ TEST (block_store, confirmation_height) GTEST_SKIP (); } auto path (nano::unique_path ()); - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, path, nano::dev::constants); nano::account account1{}; @@ -1542,7 +1545,7 @@ TEST (block_store, final_vote) GTEST_SKIP (); } auto path (nano::unique_path ()); - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, path, nano::dev::constants); { @@ -1567,7 +1570,7 @@ TEST (block_store, final_vote) TEST (block_store, incompatible_version) { auto path (nano::unique_path ()); - nano::logger_mt logger; + nano::logger logger; { auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_FALSE (store->init_error ()); @@ -1590,7 +1593,7 @@ TEST (block_store, incompatible_version) TEST (block_store, reset_renew_existing_transaction) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1630,7 +1633,7 @@ TEST (block_store, reset_renew_existing_transaction) TEST (block_store, rocksdb_force_test_env_variable) { - nano::logger_mt logger; + nano::logger logger; // Set environment variable constexpr auto env_var = "TEST_USE_ROCKSDB"; @@ -1660,7 +1663,7 @@ TEST (rocksdb_block_store, tombstone_count) GTEST_SKIP (); } nano::test::system system; - nano::logger_mt logger; + nano::logger logger; auto store = std::make_unique (logger, nano::unique_path () / "rocksdb", nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::block_builder builder; @@ -1671,7 +1674,7 @@ TEST (rocksdb_block_store, tombstone_count) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); // Enqueues a block to be saved in the database nano::account account{ 1 }; store->account.put (store->tx_begin_write (), account, nano::account_info{}); diff --git a/nano/core_test/blockprocessor.cpp b/nano/core_test/blockprocessor.cpp index 9bcc43a048..381cd1a915 100644 --- a/nano/core_test/blockprocessor.cpp +++ b/nano/core_test/blockprocessor.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -32,7 +33,7 @@ TEST (block_processor, broadcast_block_on_arrival) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Adds a block to the first node. process_active() -> (calls) block_processor.add() -> add() -> // awakes process_block() -> process_batch() -> process_one() -> process_live() node1->process_active (send1); diff --git a/nano/core_test/bootstrap.cpp b/nano/core_test/bootstrap.cpp index 963385d594..34617b1d0a 100644 --- a/nano/core_test/bootstrap.cpp +++ b/nano/core_test/bootstrap.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include #include @@ -69,7 +71,7 @@ TEST (bulk_pull, end_not_owned) open->refresh (); open->signature = nano::sign_message (key2.prv, key2.pub, open->hash ()); system.nodes[0]->work_generate_blocking (*open); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (*open).code); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (open)); auto connection (std::make_shared (std::make_shared (*system.nodes[0], nano::transport::socket::endpoint_type_t::server), system.nodes[0])); auto req = std::make_unique (nano::dev::network_params.network); req->start = key2.pub; @@ -120,9 +122,9 @@ TEST (bulk_pull, ascending_one_hash) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node.work_generate_blocking (*block1); - ASSERT_EQ (nano::process_result::progress, node.process (*block1).code); + ASSERT_EQ (nano::block_status::progress, node.process (block1)); auto socket = std::make_shared (node, nano::transport::socket::endpoint_type_t::server); auto connection = std::make_shared (socket, system.nodes[0]); auto req = std::make_unique (nano::dev::network_params.network); @@ -152,13 +154,13 @@ TEST (bulk_pull, ascending_two_account) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node.work_generate_blocking (*block1); - ASSERT_EQ (nano::process_result::progress, node.process (*block1).code); + ASSERT_EQ (nano::block_status::progress, node.process (block1)); auto socket = std::make_shared (node, nano::transport::socket::endpoint_type_t::server); auto connection = std::make_shared (socket, system.nodes[0]); auto req = std::make_unique (nano::dev::network_params.network); - req->start = nano::dev::genesis->account (); + req->start = nano::dev::genesis_key.pub; req->end.clear (); req->header.flag_set (nano::message_header::bulk_pull_ascending_flag); auto request = std::make_shared (connection, std::move (req)); @@ -187,9 +189,9 @@ TEST (bulk_pull, ascending_end) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node.work_generate_blocking (*block1); - ASSERT_EQ (nano::process_result::progress, node.process (*block1).code); + ASSERT_EQ (nano::block_status::progress, node.process (block1)); auto socket = std::make_shared (node, nano::transport::socket::endpoint_type_t::server); auto connection = std::make_shared (socket, system.nodes[0]); auto req = std::make_unique (nano::dev::network_params.network); @@ -248,16 +250,16 @@ TEST (bulk_pull, count_limit) .balance (1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (node0->latest (nano::dev::genesis_key.pub))) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (send1)); auto receive1 = builder .receive () .previous (send1->hash ()) .source (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (receive1)); auto connection (std::make_shared (std::make_shared (*node0, nano::transport::socket::endpoint_type_t::server), node0)); auto req = std::make_unique (nano::dev::network_params.network); @@ -280,17 +282,19 @@ TEST (bulk_pull, count_limit) ASSERT_EQ (nullptr, block); } -TEST (bootstrap_processor, DISABLED_process_none) +TEST (bootstrap_processor, process_none) { nano::test::system system (1); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node1->init_error ()); - auto done (false); + auto node0 = system.nodes[0]; + auto node1 = system.make_disconnected_node (); + + bool done = false; + node0->observers.socket_accepted.add ([&] (nano::transport::socket & socket) { + done = true; + }); + node1->bootstrap_initiator.bootstrap (system.nodes[0]->network.endpoint (), false); - while (!done) - { - system.io_ctx.run_one (); - } + ASSERT_TIMELY (5s, done); node1->stop (); } @@ -307,15 +311,13 @@ TEST (bootstrap_processor, process_one) system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 100)); ASSERT_NE (nullptr, send); + ASSERT_TIMELY (5s, node0->latest (nano::dev::genesis_key.pub) != nano::dev::genesis->hash ()); - node_config.peering_port = system.get_available_port (); node_flags.disable_rep_crawler = true; - auto node1 (std::make_shared (system.io_ctx, nano::unique_path (), node_config, system.work, node_flags)); - nano::block_hash hash1 (node0->latest (nano::dev::genesis_key.pub)); - nano::block_hash hash2 (node1->latest (nano::dev::genesis_key.pub)); - ASSERT_NE (hash1, hash2); + node_config.peering_port = system.get_available_port (); + auto node1 = system.make_disconnected_node (node_config, node_flags); + ASSERT_NE (node0->latest (nano::dev::genesis_key.pub), node1->latest (nano::dev::genesis_key.pub)); node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_NE (node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); ASSERT_TIMELY_EQ (10s, node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); node1->stop (); } @@ -329,20 +331,15 @@ TEST (bootstrap_processor, process_two) node_flags.disable_bootstrap_bulk_push_client = true; auto node0 (system.add_node (config, node_flags)); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - nano::block_hash hash1 (node0->latest (nano::dev::genesis_key.pub)); - ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 50)); - nano::block_hash hash2 (node0->latest (nano::dev::genesis_key.pub)); - ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 50)); - nano::block_hash hash3 (node0->latest (nano::dev::genesis_key.pub)); - ASSERT_NE (hash1, hash2); - ASSERT_NE (hash1, hash3); - ASSERT_NE (hash2, hash3); - - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node1->init_error ()); - node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_NE (node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); - ASSERT_TIMELY_EQ (10s, node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); + ASSERT_TRUE (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 50)); + ASSERT_TRUE (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 50)); + ASSERT_TIMELY_EQ (5s, nano::test::account_info (*node0, nano::dev::genesis_key.pub).block_count, 3); + + // create a node manually to avoid making automatic network connections + auto node1 = system.make_disconnected_node (); + ASSERT_NE (node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); // nodes should be out of sync here + node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); // bootstrap triggered + ASSERT_TIMELY_EQ (5s, node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); // nodes should sync up node1->stop (); } @@ -366,7 +363,7 @@ TEST (bootstrap_processor, process_state) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); auto block2 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -376,20 +373,19 @@ TEST (bootstrap_processor, process_state) .link (block1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node0->work_generate_blocking (*block1); node0->work_generate_blocking (*block2); - ASSERT_EQ (nano::process_result::progress, node0->process (*block1).code); - ASSERT_EQ (nano::process_result::progress, node0->process (*block2).code); + ASSERT_EQ (nano::block_status::progress, node0->process (block1)); + ASSERT_EQ (nano::block_status::progress, node0->process (block2)); + ASSERT_TIMELY_EQ (5s, nano::test::account_info (*node0, nano::dev::genesis_key.pub).block_count, 3); - config.peering_port = system.get_available_port (); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); + auto node1 = system.make_disconnected_node (std::nullopt, node_flags); ASSERT_EQ (node0->latest (nano::dev::genesis_key.pub), block2->hash ()); ASSERT_NE (node1->latest (nano::dev::genesis_key.pub), block2->hash ()); node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_NE (node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); - ASSERT_TIMELY_EQ (10s, node1->latest (nano::dev::genesis_key.pub), node0->latest (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, node1->latest (nano::dev::genesis_key.pub), block2->hash ()); node1->stop (); } @@ -400,26 +396,35 @@ TEST (bootstrap_processor, process_new) config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; - auto node1 (system.add_node (config, node_flags)); + nano::keypair key2; + + auto node1 = system.add_node (config, node_flags); config.peering_port = system.get_available_port (); - auto node2 (system.add_node (config, node_flags)); + auto node2 = system.add_node (config, node_flags); + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - nano::keypair key2; system.wallet (1)->insert_adhoc (key2.prv); - auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node1->config.receive_minimum.number ())); + + // send amount raw from genesis to key2, the wallet will autoreceive + auto amount = node1->config.receive_minimum.number (); + auto send = system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, amount); ASSERT_NE (nullptr, send); - ASSERT_TIMELY (10s, !node1->balance (key2.pub).is_zero ()); - auto receive (node2->block (node2->latest (key2.pub))); - ASSERT_NE (nullptr, receive); - nano::uint128_t balance1 (node1->balance (nano::dev::genesis_key.pub)); - nano::uint128_t balance2 (node1->balance (key2.pub)); - ASSERT_TIMELY (10s, node1->block_confirmed (send->hash ()) && node1->block_confirmed (receive->hash ()) && node1->active.empty () && node2->active.empty ()); // All blocks should be propagated & confirmed - - auto node3 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node3->init_error ()); + ASSERT_TIMELY (5s, !node1->balance (key2.pub).is_zero ()); + + // wait for the receive block on node2 + std::shared_ptr receive; + ASSERT_TIMELY (5s, receive = node2->block (node2->latest (key2.pub))); + + // All blocks should be propagated & confirmed + ASSERT_TIMELY (5s, nano::test::confirmed (*node1, { send, receive })); + ASSERT_TIMELY (5s, nano::test::confirmed (*node2, { send, receive })); + ASSERT_TIMELY (5s, node1->active.empty ()); + ASSERT_TIMELY (5s, node2->active.empty ()); + + // create a node manually to avoid making automatic network connections + auto node3 = system.make_disconnected_node (); node3->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node3->balance (key2.pub), balance2); - ASSERT_EQ (balance1, node3->balance (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, node3->balance (key2.pub), amount); node3->stop (); } @@ -440,8 +445,8 @@ TEST (bootstrap_processor, pull_diamond) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (node0->latest (nano::dev::genesis_key.pub))) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (send1)); auto open = builder .open () .source (send1->hash ()) @@ -449,8 +454,8 @@ TEST (bootstrap_processor, pull_diamond) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (open)); auto send2 = builder .send () .previous (open->hash ()) @@ -458,21 +463,20 @@ TEST (bootstrap_processor, pull_diamond) .balance (std::numeric_limits::max () - 100) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (send2)); auto receive = builder .receive () .previous (send1->hash ()) .source (send2->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*receive).code); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node1->init_error ()); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (receive)); + + auto node1 = system.make_disconnected_node (); node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node1->balance (nano::dev::genesis_key.pub), 100); - ASSERT_EQ (100, node1->balance (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, node1->balance (nano::dev::genesis_key.pub), 100); node1->stop (); } @@ -499,7 +503,7 @@ TEST (bootstrap_processor, DISABLED_pull_requeue_network_error) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1->bootstrap_initiator.bootstrap (node2->network.endpoint ()); auto attempt (node1->bootstrap_initiator.current_attempt ()); @@ -518,32 +522,30 @@ TEST (bootstrap_processor, DISABLED_pull_requeue_network_error) ASSERT_EQ (0, node1->stats.count (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in)); // Requeue is not increasing failed attempts } -// Test disabled because it's failing intermittently. -// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3558 -// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3559 -// CI run in which it failed: https://github.com/nanocurrency/nano-node/runs/4280675502?check_suite_focus=true#step:6:398 -TEST (bootstrap_processor, DISABLED_push_diamond) +TEST (bootstrap_processor, push_diamond) { nano::test::system system; - nano::node_config config = system.default_config (); - config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - auto node0 (system.add_node (config)); nano::keypair key; - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node1->init_error ()); + + auto node1 = system.make_disconnected_node (); auto wallet1 (node1->wallets.create (100)); wallet1->insert_adhoc (nano::dev::genesis_key.prv); wallet1->insert_adhoc (key.prv); + nano::block_builder builder; + + // send all balance from genesis to key auto send1 = builder .send () - .previous (node0->latest (nano::dev::genesis_key.pub)) + .previous (nano::dev::genesis->hash ()) .destination (key.pub) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (node0->latest (nano::dev::genesis_key.pub))) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); + + // open key account receiving all balance of genesis auto open = builder .open () .source (send1->hash ()) @@ -551,8 +553,10 @@ TEST (bootstrap_processor, DISABLED_push_diamond) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); + + // send from key to genesis 100 raw auto send2 = builder .send () .previous (open->hash ()) @@ -560,50 +564,61 @@ TEST (bootstrap_processor, DISABLED_push_diamond) .balance (std::numeric_limits::max () - 100) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); + + // receive the 100 raw on genesis auto receive = builder .receive () .previous (send1->hash ()) .source (send2->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive).code); - node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node0->balance (nano::dev::genesis_key.pub), 100); - ASSERT_EQ (100, node0->balance (nano::dev::genesis_key.pub)); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (receive)); + + nano::node_config config = system.default_config (); + config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; + nano::node_flags flags; + flags.disable_ongoing_bootstrap = true; + flags.disable_ascending_bootstrap = true; + auto node2 = system.add_node (config, flags); + node1->bootstrap_initiator.bootstrap (node2->network.endpoint (), false); + ASSERT_TIMELY_EQ (5s, node2->balance (nano::dev::genesis_key.pub), 100); node1->stop (); } -// Check that an outgoing bootstrap request can push blocks -// Test disabled because it's failing intermittently. -// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3512 -// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3517 -TEST (bootstrap_processor, DISABLED_push_diamond_pruning) +TEST (bootstrap_processor, push_diamond_pruning) { nano::test::system system; nano::node_config config = system.default_config (); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - auto node0 (system.add_node (config)); + nano::node_flags node_flags0; + node_flags0.disable_ascending_bootstrap = true; + node_flags0.disable_ongoing_bootstrap = true; + auto node0 (system.add_node (config, node_flags0)); nano::keypair key; - config.peering_port = system.get_available_port (); + config.enable_voting = false; // Remove after allowing pruned voting nano::node_flags node_flags; node_flags.enable_pruning = true; - auto node1 (std::make_shared (system.io_ctx, nano::unique_path (), config, system.work, node_flags, 1)); - ASSERT_FALSE (node1->init_error ()); - auto latest (node0->latest (nano::dev::genesis_key.pub)); + config.peering_port = system.get_available_port (); + auto node1 = system.make_disconnected_node (config, node_flags); + nano::block_builder builder; + + // send all balance from genesis to key auto send1 = builder .send () - .previous (latest) + .previous (nano::dev::genesis->hash ()) .destination (key.pub) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); + + // receive all balance on key auto open = builder .open () .source (send1->hash ()) @@ -611,12 +626,17 @@ TEST (bootstrap_processor, DISABLED_push_diamond_pruning) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); + // 1st bootstrap node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node0->balance (key.pub), nano::dev::constants.genesis_amount); + ASSERT_TIMELY_EQ (5s, node0->balance (key.pub), nano::dev::constants.genesis_amount); + ASSERT_TIMELY_EQ (5s, node1->balance (key.pub), nano::dev::constants.genesis_amount); + // Process more blocks & prune old + + // send 100 raw from key to genesis auto send2 = builder .send () .previous (open->hash ()) @@ -624,34 +644,38 @@ TEST (bootstrap_processor, DISABLED_push_diamond_pruning) .balance (std::numeric_limits::max () - 100) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); + + // receive the 100 raw from key on genesis auto receive = builder .receive () .previous (send1->hash ()) .source (send2->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (receive)); + { auto transaction (node1->store.tx_begin_write ()); ASSERT_EQ (1, node1->ledger.pruning_action (transaction, send1->hash (), 2)); ASSERT_EQ (1, node1->ledger.pruning_action (transaction, open->hash (), 1)); - ASSERT_TRUE (node1->store.block.exists (transaction, latest)); - ASSERT_FALSE (node1->store.block.exists (transaction, send1->hash ())); + ASSERT_TRUE (node1->ledger.block_exists (transaction, nano::dev::genesis->hash ())); + ASSERT_FALSE (node1->ledger.block_exists (transaction, send1->hash ())); ASSERT_TRUE (node1->store.pruned.exists (transaction, send1->hash ())); - ASSERT_FALSE (node1->store.block.exists (transaction, open->hash ())); + ASSERT_FALSE (node1->ledger.block_exists (transaction, open->hash ())); ASSERT_TRUE (node1->store.pruned.exists (transaction, open->hash ())); - ASSERT_TRUE (node1->store.block.exists (transaction, send2->hash ())); - ASSERT_TRUE (node1->store.block.exists (transaction, receive->hash ())); + ASSERT_TRUE (node1->ledger.block_exists (transaction, send2->hash ())); + ASSERT_TRUE (node1->ledger.block_exists (transaction, receive->hash ())); ASSERT_EQ (2, node1->ledger.cache.pruned_count); ASSERT_EQ (5, node1->ledger.cache.block_count); } + // 2nd bootstrap node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node0->balance (nano::dev::genesis_key.pub), 100); - ASSERT_EQ (100, node0->balance (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, node0->balance (nano::dev::genesis_key.pub), 100); + ASSERT_TIMELY_EQ (5s, node1->balance (nano::dev::genesis_key.pub), 100); node1->stop (); } @@ -662,16 +686,19 @@ TEST (bootstrap_processor, push_one) config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node0 (system.add_node (config)); nano::keypair key1; - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - auto wallet (node1->wallets.create (nano::random_wallet_id ())); + auto node1 = system.make_disconnected_node (); + auto wallet = node1->wallets.create (nano::random_wallet_id ()); ASSERT_NE (nullptr, wallet); wallet->insert_adhoc (nano::dev::genesis_key.prv); - nano::uint128_t balance1 (node1->balance (nano::dev::genesis_key.pub)); - auto send (wallet->send_action (nano::dev::genesis_key.pub, key1.pub, 100)); + + // send 100 raw from genesis to key1 + nano::uint128_t genesis_balance = node1->balance (nano::dev::genesis_key.pub); + auto send = wallet->send_action (nano::dev::genesis_key.pub, key1.pub, 100); ASSERT_NE (nullptr, send); - ASSERT_NE (balance1, node1->balance (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, genesis_balance - 100, node1->balance (nano::dev::genesis_key.pub)); + node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); - ASSERT_TIMELY (10s, node0->balance (nano::dev::genesis_key.pub) != balance1); + ASSERT_TIMELY_EQ (5s, node0->balance (nano::dev::genesis_key.pub), genesis_balance - 100); node1->stop (); } @@ -697,7 +724,7 @@ TEST (bootstrap_processor, lazy_hash) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -707,7 +734,7 @@ TEST (bootstrap_processor, lazy_hash) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -717,7 +744,7 @@ TEST (bootstrap_processor, lazy_hash) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); auto receive2 = builder .make_block () .account (key2.pub) @@ -727,16 +754,17 @@ TEST (bootstrap_processor, lazy_hash) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); // Processing test chain node0->block_processor.add (send1); node0->block_processor.add (receive1); node0->block_processor.add (send2); node0->block_processor.add (receive2); - node0->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*node0, { send1, receive1, send2, receive2 })); + // Start lazy bootstrap with last block in chain known - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 = system.make_disconnected_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); node1->bootstrap_initiator.bootstrap_lazy (receive2->hash (), true); { @@ -771,7 +799,7 @@ TEST (bootstrap_processor, lazy_hash_bootstrap_id) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -781,7 +809,7 @@ TEST (bootstrap_processor, lazy_hash_bootstrap_id) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -791,7 +819,7 @@ TEST (bootstrap_processor, lazy_hash_bootstrap_id) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); auto receive2 = builder .make_block () .account (key2.pub) @@ -801,16 +829,17 @@ TEST (bootstrap_processor, lazy_hash_bootstrap_id) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); // Processing test chain node0->block_processor.add (send1); node0->block_processor.add (receive1); node0->block_processor.add (send2); node0->block_processor.add (receive2); - node0->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*node0, { send1, receive1, send2, receive2 })); + // Start lazy bootstrap with last block in chain known - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 = system.make_disconnected_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); node1->bootstrap_initiator.bootstrap_lazy (receive2->hash (), true, "123456"); { @@ -832,13 +861,11 @@ TEST (bootstrap_processor, lazy_hash_pruning) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.enable_pruning = true; - auto node0 (system.add_node (config, node_flags)); - nano::keypair key1; - nano::keypair key2; - // Generating test chain + auto node0 = system.add_node (config, node_flags); nano::state_block_builder builder; + // send Gxrb_ratio raw from genesis to genesis auto send1 = builder .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -847,7 +874,9 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); + + // receive send1 auto receive1 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -857,7 +886,10 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); + + // change rep of genesis account to be key1 + nano::keypair key1; auto change1 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -867,7 +899,10 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); + + // change rep of genesis account to be rep2 + nano::keypair key2; auto change2 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -877,7 +912,9 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (change1->hash ())) - .build_shared (); + .build (); + + // send Gxrb_ratio from genesis to key1 and genesis rep back to genesis account auto send2 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -887,7 +924,9 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (change2->hash ())) - .build_shared (); + .build (); + + // receive send2 and rep of key1 to be itself auto receive2 = builder .make_block () .account (key1.pub) @@ -897,7 +936,9 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (send2->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); + + // send Gxrb_ratio raw, all available balance, from key1 to key2 auto send3 = builder .make_block () .account (key1.pub) @@ -907,7 +948,9 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive2->hash ())) - .build_shared (); + .build (); + + // receive send3 on key2, set rep of key2 to be itself auto receive3 = builder .make_block () .account (key2.pub) @@ -917,41 +960,44 @@ TEST (bootstrap_processor, lazy_hash_pruning) .link (send3->hash ()) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); + + std::vector> blocks = { send1, receive1, change1, change2, send2, receive2, send3, receive3 }; + ASSERT_TRUE (nano::test::process (*node0, blocks)); + ASSERT_TRUE (nano::test::start_elections (system, *node0, blocks, true)); + ASSERT_TIMELY (5s, nano::test::confirmed (*node0, blocks)); - // Processing test chain - node0->block_processor.add (send1); - node0->block_processor.add (receive1); - node0->block_processor.add (change1); - node0->block_processor.add (change2); - node0->block_processor.add (send2); - node0->block_processor.add (receive2); - node0->block_processor.add (send3); - node0->block_processor.add (receive3); - ASSERT_TIMELY_EQ (5s, 9, node0->ledger.cache.block_count); - // Processing chain to prune for node1 config.peering_port = system.get_available_port (); - auto node1 (std::make_shared (system.io_ctx, nano::unique_path (), config, system.work, node_flags, 1)); - node1->start (); + auto node1 = system.make_disconnected_node (config, node_flags); + + // Processing chain to prune for node1 node1->process_active (send1); node1->process_active (receive1); node1->process_active (change1); node1->process_active (change2); - ASSERT_TIMELY (5s, node1->block (change2->hash ()) != nullptr); + ASSERT_TIMELY (5s, nano::test::exists (*node1, { send1, receive1, change1, change2 })); + // Confirm last block to prune previous ASSERT_TRUE (nano::test::start_elections (system, *node1, { send1, receive1, change1, change2 }, true)); - ASSERT_TIMELY (5s, node1->block_confirmed (send1->hash ()) && node1->block_confirmed (receive1->hash ()) && node1->block_confirmed (change1->hash ()) && node1->block_confirmed (change2->hash ()) && node1->active.empty ()); + ASSERT_TIMELY (5s, node1->block_confirmed (send1->hash ())); + ASSERT_TIMELY (5s, node1->block_confirmed (receive1->hash ())); + ASSERT_TIMELY (5s, node1->block_confirmed (change1->hash ())); + ASSERT_TIMELY (5s, node1->block_confirmed (change2->hash ())); + ASSERT_TIMELY (5s, node1->active.empty ()); ASSERT_EQ (5, node1->ledger.cache.block_count); ASSERT_EQ (5, node1->ledger.cache.cemented_count); + // Pruning action - node1->ledger_pruning (2, false, false); + node1->ledger_pruning (2, false); ASSERT_EQ (9, node0->ledger.cache.block_count); ASSERT_EQ (0, node0->ledger.cache.pruned_count); ASSERT_EQ (5, node1->ledger.cache.block_count); ASSERT_EQ (3, node1->ledger.cache.pruned_count); + // Start lazy bootstrap with last block in chain known nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); node1->bootstrap_initiator.bootstrap_lazy (receive3->hash (), true); + // Check processed blocks ASSERT_TIMELY_EQ (5s, node1->ledger.cache.block_count, 9); ASSERT_TIMELY (5s, node1->balance (key2.pub) != 0); @@ -981,7 +1027,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -991,7 +1037,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -1001,7 +1047,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); auto receive2 = builder .make_block () .account (key2.pub) @@ -1011,7 +1057,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); auto change1 = builder .make_block () .account (key2.pub) @@ -1021,7 +1067,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (0) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (receive2->hash ())) - .build_shared (); + .build (); auto change2 = builder .make_block () .account (key2.pub) @@ -1031,7 +1077,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (0) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (change1->hash ())) - .build_shared (); + .build (); auto change3 = builder .make_block () .account (key2.pub) @@ -1041,7 +1087,7 @@ TEST (bootstrap_processor, lazy_max_pull_count) .link (0) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (change2->hash ())) - .build_shared (); + .build (); // Processing test chain node0->block_processor.add (send1); node0->block_processor.add (receive1); @@ -1050,21 +1096,18 @@ TEST (bootstrap_processor, lazy_max_pull_count) node0->block_processor.add (change1); node0->block_processor.add (change2); node0->block_processor.add (change3); - node0->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*node0, { send1, receive1, send2, receive2, change1, change2, change3 })); + // Start lazy bootstrap with last block in chain known - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 = system.make_disconnected_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); node1->bootstrap_initiator.bootstrap_lazy (change3->hash ()); // Check processed blocks ASSERT_TIMELY (10s, node1->block (change3->hash ())); - node1->stop (); } -// Test disabled because it's failing intermittently. -// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3629 -// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3640 -TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) +TEST (bootstrap_processor, lazy_unclear_state_link) { nano::test::system system; nano::node_config config = system.default_config (); @@ -1072,9 +1115,10 @@ TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; auto node1 = system.add_node (config, node_flags); nano::keypair key; - // Generating test chain nano::block_builder builder; @@ -1087,8 +1131,8 @@ TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1098,8 +1142,8 @@ TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); auto open = builder .open () .source (send1->hash ()) @@ -1107,8 +1151,8 @@ TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto receive = builder .state () .account (key.pub) @@ -1118,19 +1162,18 @@ TEST (bootstrap_processor, DISABLED_lazy_unclear_state_link) .link (send2->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (receive)); + + ASSERT_TIMELY (5s, nano::test::exists (*node1, { send1, send2, open, receive })); + // Start lazy bootstrap with last block in chain known - auto node2 = system.add_node (system.default_config (), node_flags); + auto node2 = system.make_disconnected_node (std::nullopt, node_flags); nano::test::establish_tcp (system, *node2, node1->network.endpoint ()); node2->bootstrap_initiator.bootstrap_lazy (receive->hash ()); - // Check processed blocks - ASSERT_TIMELY (10s, !node2->bootstrap_initiator.in_progress ()); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (receive->hash ())); + ASSERT_TIMELY (5s, nano::test::exists (*node2, { send1, send2, open, receive })); ASSERT_EQ (0, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in)); + node2->stop (); } TEST (bootstrap_processor, lazy_unclear_state_link_not_existing) @@ -1141,6 +1184,8 @@ TEST (bootstrap_processor, lazy_unclear_state_link_not_existing) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; auto node1 = system.add_node (config, node_flags); nano::keypair key, key2; // Generating test chain @@ -1156,8 +1201,8 @@ TEST (bootstrap_processor, lazy_unclear_state_link_not_existing) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto open = builder .open () .source (send1->hash ()) @@ -1165,8 +1210,8 @@ TEST (bootstrap_processor, lazy_unclear_state_link_not_existing) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto send2 = builder .state () .account (key.pub) @@ -1176,22 +1221,21 @@ TEST (bootstrap_processor, lazy_unclear_state_link_not_existing) .link (key2.pub) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); // Start lazy bootstrap with last block in chain known - auto node2 = system.add_node (system.default_config (), node_flags); + auto node2 = system.make_disconnected_node (std::nullopt, node_flags); nano::test::establish_tcp (system, *node2, node1->network.endpoint ()); node2->bootstrap_initiator.bootstrap_lazy (send2->hash ()); // Check processed blocks ASSERT_TIMELY (15s, !node2->bootstrap_initiator.in_progress ()); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_TIMELY (15s, nano::test::block_or_pruned_all_exists (*node2, { send1, open, send2 })); ASSERT_EQ (1, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in)); + node2->stop (); } -TEST (bootstrap_processor, DISABLED_lazy_destinations) +TEST (bootstrap_processor, lazy_destinations) { nano::test::system system; nano::node_config config = system.default_config (); @@ -1199,12 +1243,14 @@ TEST (bootstrap_processor, DISABLED_lazy_destinations) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; auto node1 = system.add_node (config, node_flags); nano::keypair key1, key2; - // Generating test chain nano::block_builder builder; + // send Gxrb_ratio raw from genesis to key1 auto send1 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1214,8 +1260,10 @@ TEST (bootstrap_processor, DISABLED_lazy_destinations) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); + + // send Gxrb_ratio raw from genesis to key2 auto send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1225,8 +1273,10 @@ TEST (bootstrap_processor, DISABLED_lazy_destinations) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); + + // receive send1 on key1 auto open = builder .open () .source (send1->hash ()) @@ -1234,8 +1284,10 @@ TEST (bootstrap_processor, DISABLED_lazy_destinations) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); + + // receive send2 on key2 auto state_open = builder .state () .account (key2.pub) @@ -1245,19 +1297,21 @@ TEST (bootstrap_processor, DISABLED_lazy_destinations) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*state_open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (state_open)); // Start lazy bootstrap with last block in sender chain - auto node2 = system.add_node (system.default_config (), node_flags); + auto node2 = system.make_disconnected_node (std::nullopt, node_flags); nano::test::establish_tcp (system, *node2, node1->network.endpoint ()); node2->bootstrap_initiator.bootstrap_lazy (send2->hash ()); + // Check processed blocks - ASSERT_TIMELY (10s, !node2->bootstrap_initiator.in_progress ()); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (state_open->hash ())); + ASSERT_TIMELY (5s, !node2->bootstrap_initiator.in_progress ()); + ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send1->hash ())); + ASSERT_TIMELY (5s, node2->ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_FALSE (node2->ledger.block_or_pruned_exists (open->hash ())); + ASSERT_FALSE (node2->ledger.block_or_pruned_exists (state_open->hash ())); + node2->stop (); } TEST (bootstrap_processor, lazy_pruning_missing_block) @@ -1269,13 +1323,15 @@ TEST (bootstrap_processor, lazy_pruning_missing_block) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; node_flags.enable_pruning = true; auto node1 = system.add_node (config, node_flags); nano::keypair key1, key2; - // Generating test chain nano::block_builder builder; + // send from genesis to key1 auto send1 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1285,8 +1341,10 @@ TEST (bootstrap_processor, lazy_pruning_missing_block) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1->process_active (send1); + + // send from genesis to key2 auto send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -1296,8 +1354,10 @@ TEST (bootstrap_processor, lazy_pruning_missing_block) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); node1->process_active (send2); + + // open account key1 auto open = builder .open () .source (send1->hash ()) @@ -1305,8 +1365,10 @@ TEST (bootstrap_processor, lazy_pruning_missing_block) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); node1->process_active (open); + + // open account key2 auto state_open = builder .state () .account (key2.pub) @@ -1316,53 +1378,48 @@ TEST (bootstrap_processor, lazy_pruning_missing_block) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); + .build (); node1->process_active (state_open); ASSERT_TIMELY (5s, node1->block (state_open->hash ()) != nullptr); // Confirm last block to prune previous ASSERT_TRUE (nano::test::start_elections (system, *node1, { send1, send2, open, state_open }, true)); - ASSERT_TIMELY (5s, node1->block_confirmed (send2->hash ()) && node1->block_confirmed (open->hash ()) && node1->block_confirmed (state_open->hash ())); + ASSERT_TIMELY (5s, nano::test::confirmed (*node1, { send2, open, state_open })); ASSERT_EQ (5, node1->ledger.cache.block_count); ASSERT_EQ (5, node1->ledger.cache.cemented_count); - // Pruning action - node1->ledger_pruning (2, false, false); - ASSERT_EQ (5, node1->ledger.cache.block_count); + + // Pruning action, send1 should get pruned + ASSERT_EQ (0, node1->ledger.cache.pruned_count); + node1->ledger_pruning (2, false); ASSERT_EQ (1, node1->ledger.cache.pruned_count); - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (send1->hash ())); // true for pruned - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (state_open->hash ())); + ASSERT_EQ (5, node1->ledger.cache.block_count); + ASSERT_TRUE (node1->ledger.store.pruned.exists (node1->ledger.store.tx_begin_read (), send1->hash ())); + ASSERT_TRUE (nano::test::exists (*node1, { send2, open, state_open })); + // Start lazy bootstrap with last block in sender chain config.peering_port = system.get_available_port (); - auto node2 (std::make_shared (system.io_ctx, nano::unique_path (), config, system.work, node_flags, 1)); + auto node2 = system.make_disconnected_node (config, node_flags); nano::test::establish_tcp (system, *node2, node1->network.endpoint ()); node2->bootstrap_initiator.bootstrap_lazy (send2->hash ()); + // Check processed blocks auto lazy_attempt (node2->bootstrap_initiator.current_lazy_attempt ()); ASSERT_NE (nullptr, lazy_attempt); - ASSERT_TIMELY (5s, lazy_attempt == nullptr || lazy_attempt->stopped || lazy_attempt->requeued_pulls >= 4); + ASSERT_TIMELY (5s, lazy_attempt->stopped || lazy_attempt->requeued_pulls >= 4); + // Some blocks cannot be retrieved from pruned node - node2->block_processor.flush (); ASSERT_EQ (1, node2->ledger.cache.block_count); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (state_open->hash ())); + ASSERT_TRUE (nano::test::block_or_pruned_none_exists (*node2, { send1, send2, open, state_open })); { auto transaction (node2->store.tx_begin_read ()); ASSERT_TRUE (node2->unchecked.exists (nano::unchecked_key (send2->root ().as_block_hash (), send2->hash ()))); } + // Insert missing block node2->process_active (send1); - node2->block_processor.flush (); - ASSERT_TIMELY (5s, !node2->bootstrap_initiator.in_progress ()); - node2->block_processor.flush (); - ASSERT_EQ (3, node2->ledger.cache.block_count); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (open->hash ())); - ASSERT_FALSE (node2->ledger.block_or_pruned_exists (state_open->hash ())); + ASSERT_TIMELY_EQ (5s, 3, node2->ledger.cache.block_count); + ASSERT_TIMELY (5s, nano::test::exists (*node2, { send1, send2 })); + ASSERT_TRUE (nano::test::block_or_pruned_none_exists (*node2, { open, state_open })); node2->stop (); } @@ -1377,9 +1434,7 @@ TEST (bootstrap_processor, lazy_cancel) nano::keypair key1; // Generating test chain - nano::state_block_builder builder; - - auto send1 = builder + auto send1 = nano::state_block_builder () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) .representative (nano::dev::genesis_key.pub) @@ -1387,10 +1442,10 @@ TEST (bootstrap_processor, lazy_cancel) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Start lazy bootstrap with last block in chain known - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 = system.make_disconnected_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); node1->bootstrap_initiator.bootstrap_lazy (send1->hash (), true); // Start "confirmed" block bootstrap { @@ -1411,6 +1466,8 @@ TEST (bootstrap_processor, wallet_lazy_frontier) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; auto node0 = system.add_node (config, node_flags); nano::keypair key1; nano::keypair key2; @@ -1426,7 +1483,7 @@ TEST (bootstrap_processor, wallet_lazy_frontier) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -1436,7 +1493,7 @@ TEST (bootstrap_processor, wallet_lazy_frontier) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -1446,7 +1503,7 @@ TEST (bootstrap_processor, wallet_lazy_frontier) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); auto receive2 = builder .make_block () .account (key2.pub) @@ -1456,16 +1513,17 @@ TEST (bootstrap_processor, wallet_lazy_frontier) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node0->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); // Processing test chain node0->block_processor.add (send1); node0->block_processor.add (receive1); node0->block_processor.add (send2); node0->block_processor.add (receive2); - node0->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*node0, { send1, receive1, send2, receive2 })); + // Start wallet lazy bootstrap - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 = system.make_disconnected_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); auto wallet (node1->wallets.create (nano::random_wallet_id ())); ASSERT_NE (nullptr, wallet); @@ -1489,6 +1547,8 @@ TEST (bootstrap_processor, wallet_lazy_pending) nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_legacy_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; + node_flags.disable_ongoing_bootstrap = true; auto node0 = system.add_node (config, node_flags); nano::keypair key1; nano::keypair key2; @@ -1504,7 +1564,7 @@ TEST (bootstrap_processor, wallet_lazy_pending) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -1514,7 +1574,7 @@ TEST (bootstrap_processor, wallet_lazy_pending) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -1524,13 +1584,14 @@ TEST (bootstrap_processor, wallet_lazy_pending) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node0->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); // Processing test chain node0->block_processor.add (send1); node0->block_processor.add (receive1); node0->block_processor.add (send2); - node0->block_processor.flush (); + nano::test::exists (*node0, { send1, receive1, send2 }); + // Start wallet lazy bootstrap auto node1 = system.add_node (); nano::test::establish_tcp (system, *node1, node0->network.endpoint ()); @@ -1564,7 +1625,7 @@ TEST (bootstrap_processor, multiple_attempts) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder .make_block () .account (key1.pub) @@ -1574,7 +1635,7 @@ TEST (bootstrap_processor, multiple_attempts) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node1->work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .make_block () .account (key1.pub) @@ -1584,7 +1645,7 @@ TEST (bootstrap_processor, multiple_attempts) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*node1->work_generate_blocking (receive1->hash ())) - .build_shared (); + .build (); auto receive2 = builder .make_block () .account (key2.pub) @@ -1594,18 +1655,20 @@ TEST (bootstrap_processor, multiple_attempts) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node1->work_generate_blocking (key2.pub)) - .build_shared (); + .build (); // Processing test chain node1->block_processor.add (send1); node1->block_processor.add (receive1); node1->block_processor.add (send2); node1->block_processor.add (receive2); - node1->block_processor.flush (); + nano::test::exists (*node1, { send1, receive1, send2, receive2 }); + // Start 2 concurrent bootstrap attempts nano::node_config node_config = system.default_config (); node_config.bootstrap_initiator_threads = 3; - auto node2 (std::make_shared (system.io_ctx, nano::unique_path (), node_config, system.work)); + + auto node2 = system.make_disconnected_node (node_config); nano::test::establish_tcp (system, *node2, node1->network.endpoint ()); node2->bootstrap_initiator.bootstrap_lazy (receive2->hash (), true); node2->bootstrap_initiator.bootstrap (); @@ -1681,9 +1744,9 @@ TEST (frontier_req, count) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*send1); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto receive1 = builder .make_block () .account (key1.pub) @@ -1693,9 +1756,9 @@ TEST (frontier_req, count) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*receive1); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive1).code); + ASSERT_EQ (nano::block_status::progress, node1->process (receive1)); auto connection (std::make_shared (std::make_shared (*node1, nano::transport::socket::endpoint_type_t::server), node1)); auto req = std::make_unique (nano::dev::network_params.network); @@ -1776,9 +1839,9 @@ TEST (frontier_req, confirmed_frontier) .link (key_before_genesis.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*send1); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto send2 = builder .make_block () .account (nano::dev::genesis_key.pub) @@ -1788,9 +1851,9 @@ TEST (frontier_req, confirmed_frontier) .link (key_after_genesis.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*send2); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); auto receive1 = builder .make_block () .account (key_before_genesis.pub) @@ -1800,9 +1863,9 @@ TEST (frontier_req, confirmed_frontier) .link (send1->hash ()) .sign (key_before_genesis.prv, key_before_genesis.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*receive1); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive1).code); + ASSERT_EQ (nano::block_status::progress, node1->process (receive1)); auto receive2 = builder .make_block () .account (key_after_genesis.pub) @@ -1812,9 +1875,9 @@ TEST (frontier_req, confirmed_frontier) .link (send2->hash ()) .sign (key_after_genesis.prv, key_after_genesis.pub) .work (0) - .build_shared (); + .build (); node1->work_generate_blocking (*receive2); - ASSERT_EQ (nano::process_result::progress, node1->process (*receive2).code); + ASSERT_EQ (nano::block_status::progress, node1->process (receive2)); // Request for all accounts (confirmed only) auto connection (std::make_shared (std::make_shared (*node1, nano::transport::socket::endpoint_type_t::server), node1)); @@ -1911,15 +1974,15 @@ TEST (frontier_req, confirmed_frontier) TEST (bulk, genesis) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config = system.default_config (); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; auto node1 = system.add_node (config, node_flags); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node2->init_error ()); + + auto node2 = system.make_disconnected_node (); nano::block_hash latest1 (node1->latest (nano::dev::genesis_key.pub)); nano::block_hash latest2 (node2->latest (nano::dev::genesis_key.pub)); ASSERT_EQ (latest1, latest2); @@ -1938,64 +2001,60 @@ TEST (bulk, genesis) TEST (bulk, offline_send) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config = system.default_config (); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; + auto node1 = system.add_node (config, node_flags); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); - ASSERT_FALSE (node2->init_error ()); - node2->start (); - system.nodes.push_back (node2); + const auto amount = node1->config.receive_minimum.number (); + auto node2 = system.make_disconnected_node (); nano::keypair key2; auto wallet (node2->wallets.create (nano::random_wallet_id ())); wallet->insert_adhoc (key2.prv); - auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node1->config.receive_minimum.number ())); + + // send amount from genesis to key2, it will be autoreceived + auto send1 = system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, amount); ASSERT_NE (nullptr, send1); - ASSERT_NE (std::numeric_limits::max (), node1->balance (nano::dev::genesis_key.pub)); - node1->block_processor.flush (); + // Wait to finish election background tasks - ASSERT_TIMELY (10s, node1->active.empty ()); - ASSERT_TIMELY (10s, node1->block_confirmed (send1->hash ())); + ASSERT_TIMELY (5s, node1->active.empty ()); + ASSERT_TIMELY (5s, node1->block_confirmed (send1->hash ())); + ASSERT_EQ (std::numeric_limits::max () - amount, node1->balance (nano::dev::genesis_key.pub)); + // Initiate bootstrap node2->bootstrap_initiator.bootstrap (node1->network.endpoint ()); - // Nodes should find each other - system.deadline_set (10s); - do - { - ASSERT_NO_ERROR (system.poll ()); - } while (node1->network.empty () || node2->network.empty ()); + + // Nodes should find each other after bootstrap initiation + ASSERT_TIMELY (5s, !node1->network.empty ()); + ASSERT_TIMELY (5s, !node2->network.empty ()); + // Send block arrival via bootstrap - ASSERT_TIMELY (10s, node2->balance (nano::dev::genesis_key.pub) != std::numeric_limits::max ()); + ASSERT_TIMELY_EQ (5s, node2->balance (nano::dev::genesis_key.pub), std::numeric_limits::max () - amount); // Receiving send block - ASSERT_TIMELY_EQ (20s, node2->balance (key2.pub), node1->config.receive_minimum.number ()); + ASSERT_TIMELY_EQ (5s, node2->balance (key2.pub), amount); node2->stop (); } -// Test disabled because it's failing intermittently. -// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3611 -// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3613 -TEST (bulk, DISABLED_genesis_pruning) +TEST (bulk, genesis_pruning) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config = system.default_config (); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; config.enable_voting = false; // Remove after allowing pruned voting nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; node_flags.disable_ongoing_bootstrap = true; + node_flags.disable_ascending_bootstrap = true; node_flags.enable_pruning = true; + auto node1 = system.add_node (config, node_flags); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - node_flags.enable_pruning = false; - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); - ASSERT_FALSE (node2->init_error ()); - nano::block_hash latest1 (node1->latest (nano::dev::genesis_key.pub)); - nano::block_hash latest2 (node2->latest (nano::dev::genesis_key.pub)); - ASSERT_EQ (latest1, latest2); + + // do 3 sends from genesis to key2 nano::keypair key2; auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, 100)); ASSERT_NE (nullptr, send1); @@ -2003,60 +2062,58 @@ TEST (bulk, DISABLED_genesis_pruning) ASSERT_NE (nullptr, send2); auto send3 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, 100)); ASSERT_NE (nullptr, send3); + { auto transaction (node1->wallets.tx_begin_write ()); system.wallet (0)->store.erase (transaction, nano::dev::genesis_key.pub); } - nano::block_hash latest3 (node1->latest (nano::dev::genesis_key.pub)); - ASSERT_NE (latest1, latest3); - ASSERT_EQ (send3->hash (), latest3); - // Confirm last block to prune previous - { - auto election = node1->active.election (send1->qualified_root ()); - ASSERT_NE (nullptr, election); - election->force_confirm (); - } - ASSERT_TIMELY (2s, node1->block_confirmed (send1->hash ()) && node1->active.active (send2->qualified_root ())); + + ASSERT_TIMELY_EQ (5s, send3->hash (), node1->latest (nano::dev::genesis_key.pub)); + + ASSERT_TRUE (nano::test::start_elections (system, *node1, { send1 }, true)); + ASSERT_TIMELY (5s, node1->active.active (send2->qualified_root ())); ASSERT_EQ (0, node1->ledger.cache.pruned_count); - { - auto election = node1->active.election (send2->qualified_root ()); - ASSERT_NE (nullptr, election); - election->force_confirm (); - } - ASSERT_TIMELY (2s, node1->block_confirmed (send2->hash ()) && node1->active.active (send3->qualified_root ())); + + ASSERT_TRUE (nano::test::start_elections (system, *node1, { send2 }, true)); + ASSERT_TIMELY (5s, node1->active.active (send3->qualified_root ())); ASSERT_EQ (0, node1->ledger.cache.pruned_count); - { - auto election = node1->active.election (send3->qualified_root ()); - ASSERT_NE (nullptr, election); - election->force_confirm (); - } - ASSERT_TIMELY (2s, node1->active.empty () && node1->block_confirmed (send3->hash ())); - node1->ledger_pruning (2, false, false); + + ASSERT_TRUE (nano::test::start_elections (system, *node1, { send3 }, true)); + ASSERT_TIMELY (5s, nano::test::confirmed (*node1, { send3 })); + + node1->ledger_pruning (2, false); ASSERT_EQ (2, node1->ledger.cache.pruned_count); ASSERT_EQ (4, node1->ledger.cache.block_count); - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (send1->hash ())); // true for pruned - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (send2->hash ())); // true for pruned - ASSERT_TRUE (node1->ledger.block_or_pruned_exists (send3->hash ())); + ASSERT_TRUE (node1->ledger.store.pruned.exists (node1->ledger.store.tx_begin_read (), send1->hash ())); + ASSERT_FALSE (nano::test::exists (*node1, { send1 })); + ASSERT_TRUE (node1->ledger.store.pruned.exists (node1->ledger.store.tx_begin_read (), send2->hash ())); + ASSERT_FALSE (nano::test::exists (*node1, { send2 })); + ASSERT_TRUE (nano::test::exists (*node1, { send3 })); + // Bootstrap with missing blocks for node2 + node_flags.enable_pruning = false; + auto node2 = system.make_disconnected_node (std::nullopt, node_flags); node2->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); node2->network.merge_peer (node1->network.endpoint ()); - ASSERT_TIMELY (25s, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::initiate, nano::stat::dir::out) >= 1 && !node2->bootstrap_initiator.in_progress ()); + ASSERT_TIMELY (5s, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::initiate, nano::stat::dir::out) >= 1); + ASSERT_TIMELY (5s, !node2->bootstrap_initiator.in_progress ()); + // node2 still missing blocks ASSERT_EQ (1, node2->ledger.cache.block_count); { auto transaction (node2->store.tx_begin_write ()); node2->unchecked.clear (); } + // Insert pruned blocks node2->process_active (send1); node2->process_active (send2); - node2->block_processor.flush (); - ASSERT_EQ (3, node2->ledger.cache.block_count); - // New bootstrap + ASSERT_TIMELY_EQ (5s, 3, node2->ledger.cache.block_count); + + // New bootstrap to sync up everything ASSERT_TIMELY_EQ (5s, node2->bootstrap_initiator.connections->connections_count, 0); node2->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); - ASSERT_TIMELY_EQ (10s, node2->latest (nano::dev::genesis_key.pub), node1->latest (nano::dev::genesis_key.pub)); - ASSERT_EQ (node2->latest (nano::dev::genesis_key.pub), node1->latest (nano::dev::genesis_key.pub)); + ASSERT_TIMELY_EQ (5s, node2->latest (nano::dev::genesis_key.pub), node1->latest (nano::dev::genesis_key.pub)); node2->stop (); } @@ -2067,9 +2124,9 @@ TEST (bulk_pull_account, basics) nano::keypair key1; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); system.wallet (0)->insert_adhoc (key1.prv); - auto send1 (system.wallet (0)->send_action (nano::dev::genesis->account (), key1.pub, 25)); - auto send2 (system.wallet (0)->send_action (nano::dev::genesis->account (), key1.pub, 10)); - auto send3 (system.wallet (0)->send_action (nano::dev::genesis->account (), key1.pub, 2)); + auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key1.pub, 25)); + auto send2 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key1.pub, 10)); + auto send3 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key1.pub, 2)); ASSERT_TIMELY_EQ (5s, system.nodes[0]->balance (key1.pub), 25); auto connection (std::make_shared (std::make_shared (*system.nodes[0], nano::transport::socket::endpoint_type_t::server), system.nodes[0])); @@ -2087,7 +2144,7 @@ TEST (bulk_pull_account, basics) auto block_data (request->get_next ()); ASSERT_EQ (send2->hash (), block_data.first.get ()->hash); ASSERT_EQ (nano::uint128_union (10), block_data.second.get ()->amount); - ASSERT_EQ (nano::dev::genesis->account (), block_data.second.get ()->source); + ASSERT_EQ (nano::dev::genesis_key.pub, block_data.second.get ()->source); ASSERT_EQ (nullptr, request->get_next ().first.get ()); } @@ -2101,7 +2158,7 @@ TEST (bulk_pull_account, basics) auto block_data (request->get_next ()); ASSERT_NE (nullptr, block_data.first.get ()); ASSERT_NE (nullptr, block_data.second.get ()); - ASSERT_EQ (nano::dev::genesis->account (), block_data.second.get ()->source); + ASSERT_EQ (nano::dev::genesis_key.pub, block_data.second.get ()->source); block_data = request->get_next (); ASSERT_EQ (nullptr, block_data.first.get ()); ASSERT_EQ (nullptr, block_data.second.get ()); diff --git a/nano/core_test/bootstrap_ascending.cpp b/nano/core_test/bootstrap_ascending.cpp index f90e5d2a7c..257b35c60f 100644 --- a/nano/core_test/bootstrap_ascending.cpp +++ b/nano/core_test/bootstrap_ascending.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -24,7 +26,7 @@ nano::block_hash random_hash () TEST (account_sets, construction) { nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -34,7 +36,7 @@ TEST (account_sets, empty_blocked) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -45,7 +47,7 @@ TEST (account_sets, block) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -57,7 +59,7 @@ TEST (account_sets, unblock) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -71,7 +73,7 @@ TEST (account_sets, priority_base) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -82,7 +84,7 @@ TEST (account_sets, priority_blocked) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -95,7 +97,7 @@ TEST (account_sets, priority_unblock_keep) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -113,7 +115,7 @@ TEST (account_sets, priority_up_down) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -128,7 +130,7 @@ TEST (account_sets, priority_down_sat) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -141,7 +143,7 @@ TEST (account_sets, saturate_priority) { nano::account account{ 1 }; nano::stats stats; - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::bootstrap_ascending::account_sets sets{ stats }; @@ -169,8 +171,8 @@ TEST (bootstrap_ascending, account_base) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0.process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0.process (send1)); auto & node1 = *system.add_node (flags); ASSERT_TIMELY (5s, node1.block (send1->hash ()) != nullptr); } @@ -192,7 +194,7 @@ TEST (bootstrap_ascending, account_inductive) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) @@ -201,12 +203,12 @@ TEST (bootstrap_ascending, account_inductive) .balance (nano::dev::constants.genesis_amount - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); // std::cerr << "Genesis: " << nano::dev::genesis->hash ().to_string () << std::endl; // std::cerr << "Send1: " << send1->hash ().to_string () << std::endl; // std::cerr << "Send2: " << send2->hash ().to_string () << std::endl; - ASSERT_EQ (nano::process_result::progress, node0.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node0.process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node0.process (send1)); + ASSERT_EQ (nano::block_status::progress, node0.process (send2)); auto & node1 = *system.add_node (flags); ASSERT_TIMELY (50s, node1.block (send2->hash ()) != nullptr); } @@ -230,7 +232,7 @@ TEST (bootstrap_ascending, trace_base) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder.make_block () .account (key.pub) .previous (0) @@ -239,7 +241,7 @@ TEST (bootstrap_ascending, trace_base) .balance (1) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); // std::cerr << "Genesis key: " << nano::dev::genesis_key.pub.to_account () << std::endl; // std::cerr << "Key: " << key.pub.to_account () << std::endl; // std::cerr << "Genesis: " << nano::dev::genesis->hash ().to_string () << std::endl; @@ -247,8 +249,8 @@ TEST (bootstrap_ascending, trace_base) // std::cerr << "receive1: " << receive1->hash ().to_string () << std::endl; auto & node1 = *system.add_node (); // std::cerr << "--------------- Start ---------------\n"; - ASSERT_EQ (nano::process_result::progress, node0.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node0.process (*receive1).code); + ASSERT_EQ (nano::block_status::progress, node0.process (send1)); + ASSERT_EQ (nano::block_status::progress, node0.process (receive1)); ASSERT_EQ (node1.store.pending.begin (node1.store.tx_begin_read (), nano::pending_key{ key.pub, 0 }), node1.store.pending.end ()); // std::cerr << "node0: " << node0.network.endpoint () << std::endl; // std::cerr << "node1: " << node1.network.endpoint () << std::endl; diff --git a/nano/core_test/bootstrap_server.cpp b/nano/core_test/bootstrap_server.cpp index 9be0f8eb94..80abdd8001 100644 --- a/nano/core_test/bootstrap_server.cpp +++ b/nano/core_test/bootstrap_server.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/core_test/confirmation_height.cpp b/nano/core_test/confirmation_height.cpp index f0db5471b6..a150d40e44 100644 --- a/nano/core_test/confirmation_height.cpp +++ b/nano/core_test/confirmation_height.cpp @@ -1,5 +1,8 @@ +#include +#include #include #include +#include #include #include @@ -49,7 +52,7 @@ TEST (confirmation_height, single) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest1)) - .build_shared (); + .build (); // Check confirmation heights before, should be uninitialized (1 for genesis). nano::confirmation_height_info confirmation_height_info; @@ -60,8 +63,7 @@ TEST (confirmation_height, single) ASSERT_EQ (nano::dev::genesis->hash (), confirmation_height_info.frontier); node->process_active (send1); - node->block_processor.flush (); - + ASSERT_TIMELY (5s, nano::test::exists (*node, { send1 })); ASSERT_TIMELY_EQ (10s, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out), 1); { @@ -132,7 +134,7 @@ TEST (confirmation_height, multiple_accounts) auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) @@ -140,7 +142,7 @@ TEST (confirmation_height, multiple_accounts) auto open2 = builder .open () .source (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key2.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) @@ -148,7 +150,7 @@ TEST (confirmation_height, multiple_accounts) auto open3 = builder .open () .source (send3->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key3.pub) .sign (key3.prv, key3.pub) .work (*system.work.generate (key3.pub)) @@ -199,20 +201,20 @@ TEST (confirmation_height, multiple_accounts) { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send3).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send3)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open3).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open3)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send4).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send5).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send4)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send5)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send6).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send6)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive2)); // Check confirmation heights of all the accounts (except genesis) are uninitialized (0), // as we have any just added them to the ledger and not processed any live transactions yet. @@ -238,7 +240,7 @@ TEST (confirmation_height, multiple_accounts) .source (send6->hash ()) .sign (key3.prv, key3.pub) .work (*system.work.generate (open3->hash ())) - .build_shared (); + .build (); node->process_active (receive3); auto election = nano::test::start_election (system, *node, receive3->hash ()); ASSERT_NE (nullptr, election); @@ -319,36 +321,36 @@ TEST (confirmation_height, gap_bootstrap) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 2 * nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); auto send3 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 3 * nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send3); auto open1 = builder .open () @@ -357,7 +359,7 @@ TEST (confirmation_height, gap_bootstrap) .account (destination.pub) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open1); // Receive @@ -367,7 +369,7 @@ TEST (confirmation_height, gap_bootstrap) .source (send2->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*receive1); auto receive2 = builder .receive () @@ -375,7 +377,7 @@ TEST (confirmation_height, gap_bootstrap) .source (send3->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*receive2); node1.block_processor.add (send1); @@ -452,36 +454,36 @@ TEST (confirmation_height, gap_live) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 1) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*send1); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 2) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*send2); auto send3 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 3) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*send3); auto open1 = builder @@ -491,7 +493,7 @@ TEST (confirmation_height, gap_live) .account (destination.pub) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*open1); auto receive1 = builder .receive () @@ -499,7 +501,7 @@ TEST (confirmation_height, gap_live) .source (send2->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*receive1); auto receive2 = builder .receive () @@ -507,20 +509,22 @@ TEST (confirmation_height, gap_live) .source (send3->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node->work_generate_blocking (*receive2); node->block_processor.add (send1); node->block_processor.add (send2); node->block_processor.add (send3); + // node->block_processor.add (open1); Witheld for test node->block_processor.add (receive1); - node->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*node, { send1, send2, send3 })); + ASSERT_TIMELY (5s, node->unchecked.exists ({ open1->hash (), receive1->hash () })); add_callback_stats (*node); // Receive 2 comes in on the live network, however the chain has not been finished so it gets added to unchecked node->process_active (receive2); - node->block_processor.flush (); + ASSERT_TIMELY (5s, node->unchecked.exists ({ receive1->hash (), receive2->hash () })); // Confirmation heights should not be updated { @@ -537,7 +541,6 @@ TEST (confirmation_height, gap_live) // Now complete the chain where the block comes in on the live network node->process_active (open1); - node->block_processor.flush (); ASSERT_TIMELY_EQ (10s, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out), 6); @@ -591,7 +594,7 @@ TEST (confirmation_height, send_receive_between_2_accounts) auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) @@ -599,7 +602,7 @@ TEST (confirmation_height, send_receive_between_2_accounts) auto send2 = builder .send () .previous (open1->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (1000) .sign (key1.prv, key1.pub) .work (*system.work.generate (open1->hash ())) @@ -607,7 +610,7 @@ TEST (confirmation_height, send_receive_between_2_accounts) auto send3 = builder .send () .previous (send2->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (900) .sign (key1.prv, key1.pub) .work (*system.work.generate (send2->hash ())) @@ -615,7 +618,7 @@ TEST (confirmation_height, send_receive_between_2_accounts) auto send4 = builder .send () .previous (send3->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (500) .sign (key1.prv, key1.pub) .work (*system.work.generate (send3->hash ())) @@ -655,7 +658,7 @@ TEST (confirmation_height, send_receive_between_2_accounts) .source (send5->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (send4->hash ())) - .build_shared (); + .build (); nano::keypair key2; auto send6 = builder .send () @@ -668,20 +671,20 @@ TEST (confirmation_height, send_receive_between_2_accounts) // Unpocketed send { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open1)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send3).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send4).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send3)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send4)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive3).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive3)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send5).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send6).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send5)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send6)); } add_callback_stats (*node); @@ -748,7 +751,7 @@ TEST (confirmation_height, send_receive_self) .source (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); auto send2 = builder .send () .previous (receive1->hash ()) @@ -778,7 +781,7 @@ TEST (confirmation_height, send_receive_self) .source (send3->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (receive2->hash ())) - .build_shared (); + .build (); // Send to another account to prevent automatic receiving on the genesis account nano::keypair key1; @@ -792,14 +795,14 @@ TEST (confirmation_height, send_receive_self) .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send3).code); - - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive3).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send4).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send3)); + + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive3)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send4)); } add_callback_stats (*node); @@ -987,7 +990,7 @@ TEST (confirmation_height, all_block_types) .link (key1.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (state_receive2->hash ())) - .build_shared (); + .build (); auto state_send3 = builder .state () .account (key2.pub) @@ -1011,9 +1014,9 @@ TEST (confirmation_height, all_block_types) .build (); auto state_receive3 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2 + 1) .link (state_send4->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -1022,30 +1025,30 @@ TEST (confirmation_height, all_block_types) { auto transaction (store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_open).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_open)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_receive).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_receive)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *change).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_change).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, change)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_change)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *epoch).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, epoch)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, epoch1)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_receive2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_receive2)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_send3).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_send3)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_send4).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *state_receive3).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_send4)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, state_receive3)); } add_callback_stats (*node); @@ -1115,8 +1118,8 @@ TEST (confirmation_height, conflict_rollback_cemented) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (genesis_hash)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*fork1a).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (fork1a)); ASSERT_TRUE (nano::test::start_elections (system, *node1, { fork1a }, true)); ASSERT_TIMELY (5s, nano::test::confirmed (*node1, { fork1a })); @@ -1130,7 +1133,7 @@ TEST (confirmation_height, conflict_rollback_cemented) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (genesis_hash)) - .build_shared (); + .build (); node1->block_processor.force (fork1b); // node2 already has send2 forced confirmed whilst node1 should have confirmed send1 and therefore we have a cemented fork on node2 @@ -1157,8 +1160,7 @@ TEST (confirmation_heightDeathTest, rollback_added_block) // valgrind can be noisy with death tests if (!nano::running_within_valgrind ()) { - nano::logger_mt logger; - nano::logging logging; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1175,7 +1177,7 @@ TEST (confirmation_heightDeathTest, rollback_added_block) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); { auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, ledger.constants); @@ -1184,13 +1186,13 @@ TEST (confirmation_heightDeathTest, rollback_added_block) uint64_t batch_write_size = 2048; std::atomic stopped{ false }; nano::confirmation_height_unbounded unbounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); // Processing a block which doesn't exist should bail ASSERT_DEATH_IF_SUPPORTED (unbounded_processor.process (send), ""); nano::confirmation_height_bounded bounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); // Processing a block which doesn't exist should bail ASSERT_DEATH_IF_SUPPORTED (bounded_processor.process (send), ""); } @@ -1215,12 +1217,11 @@ TEST (confirmation_height, observers) .balance (amount - node1->config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest1)) - .build_shared (); + .build (); add_callback_stats (*node1); node1->process_active (send1); - node1->block_processor.flush (); ASSERT_TIMELY_EQ (10s, node1->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out), 1); auto transaction = node1->store.tx_begin_read (); ASSERT_TRUE (node1->ledger.block_confirmed (transaction, send1->hash ())); @@ -1249,8 +1250,7 @@ TEST (confirmation_heightDeathTest, modified_chain) // valgrind can be noisy with death tests if (!nano::running_within_valgrind ()) { - nano::logging logging; - nano::logger_mt logger; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1267,20 +1267,20 @@ TEST (confirmation_heightDeathTest, modified_chain) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); { auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, ledger.constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); } uint64_t batch_write_size = 2048; std::atomic stopped{ false }; nano::confirmation_height_bounded bounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); { - // This reads the blocks in the account, but prevents any writes from occuring yet + // This reads the blocks in the account, but prevents any writes from occurring yet auto scoped_write_guard = write_database_queue.wait (nano::writer::testing); bounded_processor.process (send); } @@ -1292,14 +1292,14 @@ TEST (confirmation_heightDeathTest, modified_chain) ASSERT_DEATH_IF_SUPPORTED (bounded_processor.cement_blocks (scoped_write_guard), ""); } - ASSERT_EQ (nano::process_result::progress, ledger.process (store->tx_begin_write (), *send).code); - store->confirmation_height.put (store->tx_begin_write (), nano::dev::genesis->account (), { 1, nano::dev::genesis->hash () }); + ASSERT_EQ (nano::block_status::progress, ledger.process (store->tx_begin_write (), send)); + store->confirmation_height.put (store->tx_begin_write (), nano::dev::genesis_key.pub, { 1, nano::dev::genesis->hash () }); nano::confirmation_height_unbounded unbounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); { - // This reads the blocks in the account, but prevents any writes from occuring yet + // This reads the blocks in the account, but prevents any writes from occurring yet auto scoped_write_guard = write_database_queue.wait (nano::writer::testing); unbounded_processor.process (send); } @@ -1327,8 +1327,7 @@ TEST (confirmation_heightDeathTest, modified_chain_account_removed) // valgrind can be noisy with death tests if (!nano::running_within_valgrind ()) { - nano::logging logging; - nano::logger_mt logger; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1345,7 +1344,7 @@ TEST (confirmation_heightDeathTest, modified_chain_account_removed) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto open = builder .state () .account (key1.pub) @@ -1355,21 +1354,21 @@ TEST (confirmation_heightDeathTest, modified_chain_account_removed) .link (send->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) - .build_shared (); + .build (); { auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, ledger.constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); } uint64_t batch_write_size = 2048; std::atomic stopped{ false }; nano::confirmation_height_unbounded unbounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); { - // This reads the blocks in the account, but prevents any writes from occuring yet + // This reads the blocks in the account, but prevents any writes from occurring yet auto scoped_write_guard = write_database_queue.wait (nano::writer::testing); unbounded_processor.process (open); } @@ -1382,14 +1381,14 @@ TEST (confirmation_heightDeathTest, modified_chain_account_removed) } // Reset conditions and test with the bounded processor - ASSERT_EQ (nano::process_result::progress, ledger.process (store->tx_begin_write (), *open).code); - store->confirmation_height.put (store->tx_begin_write (), nano::dev::genesis->account (), { 1, nano::dev::genesis->hash () }); + ASSERT_EQ (nano::block_status::progress, ledger.process (store->tx_begin_write (), open)); + store->confirmation_height.put (store->tx_begin_write (), nano::dev::genesis_key.pub, { 1, nano::dev::genesis->hash () }); nano::confirmation_height_bounded bounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [] (auto const &) {}, [] (auto const &) {}, [] () { return 0; }); { - // This reads the blocks in the account, but prevents any writes from occuring yet + // This reads the blocks in the account, but prevents any writes from occurring yet auto scoped_write_guard = write_database_queue.wait (nano::writer::testing); bounded_processor.process (open); } @@ -1433,12 +1432,12 @@ TEST (confirmation_height, pending_observer_callbacks) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); } add_callback_stats (*node); @@ -1482,10 +1481,10 @@ TEST (confirmation_height, callback_confirmed_history) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } auto send1 = builder @@ -1495,22 +1494,18 @@ TEST (confirmation_height, callback_confirmed_history) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); add_callback_stats (*node); node->process_active (send1); - ASSERT_NE (nano::test::start_election (system, *node, send1->hash ()), nullptr); + std::shared_ptr election; + ASSERT_TIMELY (5s, election = nano::test::start_election (system, *node, send1->hash ())); { - node->process_active (send); - node->block_processor.flush (); - // The write guard prevents the confirmation height processor doing any writes auto write_guard = node->write_database_queue.wait (nano::writer::testing); // Confirm send1 - auto election = node->active.election (send1->qualified_root ()); - ASSERT_NE (nullptr, election); election->force_confirm (); ASSERT_TIMELY_EQ (10s, node->active.size (), 0); ASSERT_EQ (0, node->active.recently_cemented.list ().size ()); @@ -1574,7 +1569,7 @@ TEST (confirmation_height, dependent_election) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto send1 = builder .send () .previous (send->hash ()) @@ -1582,7 +1577,7 @@ TEST (confirmation_height, dependent_election) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); auto send2 = builder .send () .previous (send1->hash ()) @@ -1590,12 +1585,12 @@ TEST (confirmation_height, dependent_election) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 3) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); } add_callback_stats (*node); @@ -1669,7 +1664,7 @@ TEST (confirmation_height, cemented_gap_below_receive) auto open = builder .open () .source (send->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) @@ -1728,29 +1723,29 @@ TEST (confirmation_height, cemented_gap_below_receive) auto open1 = builder .open () .source (send3->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key2.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send1)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send3).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send3)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send2)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open1)); } std::vector observer_order; @@ -1829,7 +1824,7 @@ TEST (confirmation_height, cemented_gap_below_no_cache) auto open = builder .open () .source (send->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) @@ -1888,35 +1883,35 @@ TEST (confirmation_height, cemented_gap_below_no_cache) auto open1 = builder .open () .source (send3->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key2.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send1)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send3).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *dummy_send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send3)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, dummy_send2)); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open1)); } // Force some blocks to be cemented so that the cached confirmed info variable is empty { auto transaction (node->store.tx_begin_write ()); - node->store.confirmation_height.put (transaction, nano::dev::genesis->account (), nano::confirmation_height_info{ 3, send1->hash () }); + node->store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, nano::confirmation_height_info{ 3, send1->hash () }); node->store.confirmation_height.put (transaction, key1.pub, nano::confirmation_height_info{ 2, receive1->hash () }); } @@ -1965,8 +1960,8 @@ TEST (confirmation_height, election_winner_details_clearing) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->process (send1)); auto const send2 = builder.make_block () .previous (send1->hash ()) @@ -1974,8 +1969,8 @@ TEST (confirmation_height, election_winner_details_clearing) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->process (send2)); auto const send3 = builder.make_block () .previous (send2->hash ()) @@ -1983,8 +1978,8 @@ TEST (confirmation_height, election_winner_details_clearing) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 3) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send2->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->process (*send3).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->process (send3)); node->process_confirmed (nano::election_status{ send2 }); ASSERT_TIMELY (5s, node->block_confirmed (send2->hash ())); @@ -2023,7 +2018,7 @@ TEST (confirmation_height, election_winner_details_clearing_node_process_confirm .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Add to election_winner_details. Use an unrealistic iteration so that it should fall into the else case and do a cleanup node->active.add_election_winner_details (send->hash (), nullptr); nano::election_status election; @@ -2039,7 +2034,7 @@ TEST (confirmation_height, unbounded_block_cache_iteration) // Don't test this in rocksdb mode GTEST_SKIP (); } - nano::logger_mt logger; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -2048,7 +2043,6 @@ TEST (confirmation_height, unbounded_block_cache_iteration) nano::write_database_queue write_database_queue (false); boost::latch initialized_latch{ 0 }; nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::logging logging; nano::keypair key1; nano::block_builder builder; auto send = builder @@ -2058,7 +2052,7 @@ TEST (confirmation_height, unbounded_block_cache_iteration) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send1 = builder .send () .previous (send->hash ()) @@ -2066,15 +2060,15 @@ TEST (confirmation_height, unbounded_block_cache_iteration) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) - .build_shared (); + .build (); { auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, nano::dev::constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); } - nano::confirmation_height_processor confirmation_height_processor (ledger, write_database_queue, 10ms, logging, logger, initialized_latch, nano::confirmation_height_mode::unbounded); + nano::confirmation_height_processor confirmation_height_processor (ledger, write_database_queue, 10ms, logger, initialized_latch, nano::confirmation_height_mode::unbounded); nano::timer<> timer; timer.start (); { @@ -2103,8 +2097,7 @@ TEST (confirmation_height, unbounded_block_cache_iteration) TEST (confirmation_height, pruned_source) { - nano::logger_mt logger; - nano::logging logging; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -2124,7 +2117,7 @@ TEST (confirmation_height, pruned_source) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto open1 = builder .state () .account (key1.pub) @@ -2134,7 +2127,7 @@ TEST (confirmation_height, pruned_source) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) - .build_shared (); + .build (); auto send2 = builder .state () .account (key1.pub) @@ -2144,7 +2137,7 @@ TEST (confirmation_height, pruned_source) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*pool.generate (open1->hash ())) - .build_shared (); + .build (); auto send3 = builder .state () .account (key1.pub) @@ -2154,7 +2147,7 @@ TEST (confirmation_height, pruned_source) .link (key2.pub) .sign (key1.prv, key1.pub) .work (*pool.generate (send2->hash ())) - .build_shared (); + .build (); auto open2 = builder .state () .account (key2.pub) @@ -2164,21 +2157,21 @@ TEST (confirmation_height, pruned_source) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) - .build_shared (); + .build (); { auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, nano::dev::constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send3).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send3)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open2)); } uint64_t batch_write_size = 2; std::atomic stopped{ false }; bool first_time{ true }; nano::confirmation_height_bounded bounded_processor ( - ledger, write_database_queue, 10ms, logging, logger, stopped, batch_write_size, [&] (auto const & cemented_blocks_a) { + ledger, write_database_queue, 10ms, logger, stopped, batch_write_size, [&] (auto const & cemented_blocks_a) { if (first_time) { // Prune the send diff --git a/nano/core_test/confirmation_solicitor.cpp b/nano/core_test/confirmation_solicitor.cpp index c456624153..7afa210a2f 100644 --- a/nano/core_test/confirmation_solicitor.cpp +++ b/nano/core_test/confirmation_solicitor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -20,7 +21,7 @@ TEST (confirmation_solicitor, batches) auto & node2 = *system.add_node (node_flags); auto channel1 = nano::test::establish_tcp (system, node2, node1.network.endpoint ()); // Solicitor will only solicit from this representative - nano::representative representative (nano::dev::genesis_key.pub, channel1); + nano::representative representative{ nano::dev::genesis_key.pub, channel1 }; std::vector representatives{ representative }; nano::confirmation_solicitor solicitor (node2.network, node2.config); solicitor.prepare (representatives); @@ -37,7 +38,7 @@ TEST (confirmation_solicitor, batches) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); send->sideband_set ({}); { nano::lock_guard guard (node2.active.mutex); @@ -70,7 +71,7 @@ TEST (confirmation_solicitor, different_hash) auto & node2 = *system.add_node (node_flags); auto channel1 = nano::test::establish_tcp (system, node2, node1.network.endpoint ()); // Solicitor will only solicit from this representative - nano::representative representative (nano::dev::genesis_key.pub, channel1); + nano::representative representative{ nano::dev::genesis_key.pub, channel1 }; std::vector representatives{ representative }; nano::confirmation_solicitor solicitor (node2.network, node2.config); solicitor.prepare (representatives); @@ -87,7 +88,7 @@ TEST (confirmation_solicitor, different_hash) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); send->sideband_set ({}); auto election (std::make_shared (node2, send, nullptr, nullptr, nano::election_behavior::normal)); // Add a vote for something else, not the winner @@ -131,7 +132,7 @@ TEST (confirmation_solicitor, bypass_max_requests_cap) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); send->sideband_set ({}); auto election (std::make_shared (node2, send, nullptr, nullptr, nano::election_behavior::normal)); // Add a vote for something else, not the winner diff --git a/nano/core_test/conflicts.cpp b/nano/core_test/conflicts.cpp index 4232edb429..943bb75699 100644 --- a/nano/core_test/conflicts.cpp +++ b/nano/core_test/conflicts.cpp @@ -1,7 +1,8 @@ - +#include #include #include #include +#include #include #include #include @@ -25,9 +26,9 @@ TEST (conflicts, start_stop) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); ASSERT_EQ (0, node1.active.size ()); node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); @@ -52,11 +53,11 @@ TEST (conflicts, add_existing) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); // add the block to ledger as an unconfirmed block - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); // wait for send1 to be inserted in the ledger ASSERT_TIMELY (5s, node1.block (send1->hash ())); @@ -75,7 +76,7 @@ TEST (conflicts, add_existing) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); send2->sideband_set ({}); @@ -108,7 +109,7 @@ TEST (conflicts, add_two) .link (key3.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (open1->hash ())) - .build_shared (); + .build (); // send 1 raw to account key3 from key2 auto send_b = nano::state_block_builder () @@ -119,7 +120,7 @@ TEST (conflicts, add_two) .link (key3.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (open2->hash ())) - .build_shared (); + .build (); // activate elections for the previous two send blocks (to account3) that we did not forcefully confirm ASSERT_TRUE (nano::test::process (*node, { send_a, send_b })); @@ -149,10 +150,10 @@ TEST (vote_uniquer, vbh_one) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); std::vector hashes; hashes.push_back (block->hash ()); - auto vote1 (std::make_shared (key.pub, key.prv, 0, 0, hashes)); + auto vote1 = nano::test::make_vote (key, { hashes }, 0, 0); auto vote2 (std::make_shared (*vote1)); ASSERT_EQ (vote1, uniquer.unique (vote1)); ASSERT_EQ (vote1, uniquer.unique (vote2)); @@ -172,7 +173,7 @@ TEST (vote_uniquer, vbh_two) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); std::vector hashes1; hashes1.push_back (block1->hash ()); auto block2 = builder @@ -184,11 +185,11 @@ TEST (vote_uniquer, vbh_two) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); std::vector hashes2; hashes2.push_back (block2->hash ()); - auto vote1 (std::make_shared (key.pub, key.prv, 0, 0, hashes1)); - auto vote2 (std::make_shared (key.pub, key.prv, 0, 0, hashes2)); + auto vote1 = nano::test::make_vote (key, { hashes1 }, 0, 0); + auto vote2 = nano::test::make_vote (key, { hashes2 }, 0, 0); ASSERT_EQ (vote1, uniquer.unique (vote1)); ASSERT_EQ (vote2, uniquer.unique (vote2)); } diff --git a/nano/core_test/core_test_main.cc b/nano/core_test/core_test_main.cc index 6f5c4fc499..0abd1cdc3a 100644 --- a/nano/core_test/core_test_main.cc +++ b/nano/core_test/core_test_main.cc @@ -1,7 +1,7 @@ #include "gtest/gtest.h" +#include #include -#include #include #include @@ -19,13 +19,10 @@ void force_nano_dev_network (); GTEST_API_ int main (int argc, char ** argv) { - printf ("Running main() from core_test_main.cc\n"); + nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; - // Setting up logging so that there aren't any piped to standard output. - nano::logging logging; - logging.init (nano::unique_path ()); testing::InitGoogleTest (&argc, argv); auto res = RUN_ALL_TESTS (); nano::test::cleanup_dev_directories_on_exit (); diff --git a/nano/core_test/distributed_work.cpp b/nano/core_test/distributed_work.cpp index 115293bd6b..1e5e5ed4a8 100644 --- a/nano/core_test/distributed_work.cpp +++ b/nano/core_test/distributed_work.cpp @@ -18,10 +18,10 @@ TEST (distributed_work, no_peers) nano::test::system system (1); auto node (system.nodes[0]); nano::block_hash hash{ 1 }; - boost::optional work; + std::optional work; std::atomic done{ false }; - auto callback = [&work, &done] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&work, &done] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); work = work_a; done = true; }; @@ -54,8 +54,8 @@ TEST (distributed_work, no_peers_cancel) auto & node = *system.add_node (node_config); nano::block_hash hash{ 1 }; bool done{ false }; - auto callback_to_cancel = [&done] (boost::optional work_a) { - ASSERT_FALSE (work_a.is_initialized ()); + auto callback_to_cancel = [&done] (std::optional work_a) { + ASSERT_FALSE (work_a.has_value ()); done = true; }; ASSERT_FALSE (node.distributed_work.make (nano::work_version::work_1, hash, node.config.work_peers, nano::difficulty::from_multiplier (1e6, node.network_params.work.base), callback_to_cancel)); @@ -83,8 +83,8 @@ TEST (distributed_work, no_peers_multi) nano::block_hash hash{ 1 }; unsigned total{ 10 }; std::atomic count{ 0 }; - auto callback = [&count] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&count] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); ++count; }; // Test many works for the same root @@ -125,10 +125,10 @@ TEST (distributed_work, peer) auto node (system.add_node (node_config)); ASSERT_FALSE (node->local_work_generation_enabled ()); nano::block_hash hash{ 1 }; - boost::optional work; + std::optional work; std::atomic done{ false }; - auto callback = [&work, &done] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&work, &done] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); work = work_a; done = true; }; @@ -151,10 +151,10 @@ TEST (distributed_work, peer_malicious) auto node (system.nodes[0]); ASSERT_TRUE (node->local_work_generation_enabled ()); nano::block_hash hash{ 1 }; - boost::optional work; + std::optional work; std::atomic done{ false }; - auto callback = [&work, &done] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&work, &done] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); work = work_a; done = true; }; @@ -194,10 +194,10 @@ TEST (distributed_work, DISABLED_peer_multi) auto node (system.nodes[0]); ASSERT_TRUE (node->local_work_generation_enabled ()); nano::block_hash hash{ 1 }; - boost::optional work; + std::optional work; std::atomic done{ false }; - auto callback = [&work, &done] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&work, &done] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); work = work_a; done = true; }; @@ -233,10 +233,10 @@ TEST (distributed_work, fail_resolve) nano::test::system system (1); auto node (system.nodes[0]); nano::block_hash hash{ 1 }; - boost::optional work; + std::optional work; std::atomic done{ false }; - auto callback = [&work, &done] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); + auto callback = [&work, &done] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); work = work_a; done = true; }; diff --git a/nano/core_test/election.cpp b/nano/core_test/election.cpp index 24450b7802..766b41c069 100644 --- a/nano/core_test/election.cpp +++ b/nano/core_test/election.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include #include @@ -47,7 +49,7 @@ TEST (election, quorum_minimum_flip_success) .link (key1.pub) .work (*system.work.generate (latest_hash)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); nano::keypair key2{}; auto send2 = builder.make_block () @@ -58,7 +60,7 @@ TEST (election, quorum_minimum_flip_success) .link (key2.pub) .work (*system.work.generate (latest_hash)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); node1.process_active (send1); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ()) != nullptr) @@ -94,7 +96,7 @@ TEST (election, quorum_minimum_flip_fail) .link (nano::keypair{}.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) @@ -104,7 +106,7 @@ TEST (election, quorum_minimum_flip_fail) .link (nano::keypair{}.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); // process send1 and wait until its election appears node.process_active (send1); @@ -145,7 +147,7 @@ TEST (election, quorum_minimum_confirm_success) .link (key1.pub) .work (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); node1.process_active (send1); node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); @@ -177,7 +179,7 @@ TEST (election, quorum_minimum_confirm_fail) .link (nano::keypair{}.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); node1.process_active (send1); auto election = nano::test::start_election (system, node1, send1->hash ()); @@ -219,12 +221,12 @@ TEST (election, quorum_minimum_update_weight_before_quorum_checks) .balance (amount) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); node1.process_active (send1); ASSERT_TIMELY (5s, node1.block (send1->hash ()) != nullptr); - auto const open1 = nano::open_block_builder{}.make_block ().account (key1.pub).source (send1->hash ()).representative (key1.pub).sign (key1.prv, key1.pub).work (*system.work.generate (key1.pub)).build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*open1).code); + auto const open1 = nano::open_block_builder{}.make_block ().account (key1.pub).source (send1->hash ()).representative (key1.pub).sign (key1.prv, key1.pub).work (*system.work.generate (key1.pub)).build (); + ASSERT_EQ (nano::block_status::progress, node1.process (open1)); nano::keypair key2; auto const send2 = builder.make_block () @@ -233,8 +235,8 @@ TEST (election, quorum_minimum_update_weight_before_quorum_checks) .balance (3) .sign (key1.prv, key1.pub) .work (*system.work.generate (open1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1.process (send2)); ASSERT_TIMELY_EQ (5s, node1.ledger.cache.block_count, 4); node_config.peering_port = system.get_available_port (); @@ -254,7 +256,7 @@ TEST (election, quorum_minimum_update_weight_before_quorum_checks) ASSERT_NE (channel, nullptr); auto vote2 = nano::test::make_final_vote (key1, { send1->hash () }); - ASSERT_FALSE (node1.rep_crawler.response (channel, vote2, true)); + node1.rep_crawler.force_process (vote2, channel); ASSERT_FALSE (election->confirmed ()); { @@ -283,7 +285,7 @@ TEST (election, continuous_voting) .balance (node1.balance (nano::dev::genesis_key.pub) / 10 * 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); ASSERT_TRUE (nano::test::process (node1, { send1 })); ASSERT_TRUE (nano::test::start_elections (system, node1, { send1 }, true)); @@ -298,11 +300,11 @@ TEST (election, continuous_voting) .balance (node1.balance (nano::dev::genesis_key.pub) - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); ASSERT_TRUE (nano::test::process (node1, { send2 })); ASSERT_TIMELY (5s, node1.active.active (*send2)); - // Ensure votes are generated in continuous manner - ASSERT_TIMELY (5s, node1.stats.count (nano::stat::type::election, nano::stat::detail::generate_vote) >= 5); + // Ensure votes are broadcasted in continuous manner + ASSERT_TIMELY (5s, node1.stats.count (nano::stat::type::election, nano::stat::detail::broadcast_vote) >= 5); } diff --git a/nano/core_test/election_scheduler.cpp b/nano/core_test/election_scheduler.cpp index 2e17c27d50..c453bfe00e 100644 --- a/nano/core_test/election_scheduler.cpp +++ b/nano/core_test/election_scheduler.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include @@ -26,8 +28,8 @@ TEST (election_scheduler, activate_one_timely) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), *send1); + .build (); + system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), send1); system.nodes[0]->scheduler.priority.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); ASSERT_TIMELY (5s, system.nodes[0]->active.election (send1->qualified_root ())); } @@ -44,8 +46,8 @@ TEST (election_scheduler, activate_one_flush) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), *send1); + .build (); + system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), send1); system.nodes[0]->scheduler.priority.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); ASSERT_TIMELY (5s, system.nodes[0]->active.election (send1->qualified_root ())); } @@ -86,8 +88,8 @@ TEST (election_scheduler, no_vacancy) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send)); node.process_confirmed (nano::election_status{ send }); auto receive = builder.make_block () @@ -98,8 +100,8 @@ TEST (election_scheduler, no_vacancy) .balance (nano::Gxrb_ratio) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*receive).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (receive)); node.process_confirmed (nano::election_status{ receive }); // Second, process two eligible transactions @@ -111,8 +113,8 @@ TEST (election_scheduler, no_vacancy) .balance (nano::dev::constants.genesis_amount - 2 * nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*block1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (block1)); // There is vacancy so it should be inserted node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); @@ -127,8 +129,8 @@ TEST (election_scheduler, no_vacancy) .balance (0) .sign (key.prv, key.pub) .work (*system.work.generate (receive->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*block2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (block2)); // There is no vacancy so it should stay queued node.scheduler.priority.activate (key.pub, node.store.tx_begin_read ()); diff --git a/nano/core_test/enums.cpp b/nano/core_test/enums.cpp index ae60532ed2..53b25a6d33 100644 --- a/nano/core_test/enums.cpp +++ b/nano/core_test/enums.cpp @@ -7,17 +7,59 @@ TEST (enums, stat_type) { ASSERT_FALSE (nano::to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (static_cast (0)) }); + ASSERT_FALSE (nano::to_string (nano::stat::type::_last).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (nano::stat::type::_last) }); + ASSERT_EQ (nano::to_string (nano::stat::type::_last), "_last"); } TEST (enums, stat_detail) { ASSERT_FALSE (nano::to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (static_cast (0)) }); + ASSERT_FALSE (nano::to_string (nano::stat::detail::_last).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (nano::stat::detail::_last) }); + ASSERT_EQ (nano::to_string (nano::stat::detail::_last), "_last"); } TEST (enums, stat_dir) { ASSERT_FALSE (nano::to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (static_cast (0)) }); + ASSERT_FALSE (nano::to_string (nano::stat::dir::_last).empty ()); + ASSERT_NO_THROW (std::string{ nano::to_string (nano::stat::dir::_last) }); + ASSERT_EQ (nano::to_string (nano::stat::dir::_last), "_last"); +} + +TEST (enums, log_type) +{ + ASSERT_FALSE (to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ to_string (static_cast (0)) }); + + ASSERT_FALSE (to_string (nano::log::type::_last).empty ()); + ASSERT_NO_THROW (std::string{ to_string (nano::log::type::_last) }); + ASSERT_EQ (to_string (nano::log::type::_last), "_last"); +} + +TEST (enums, log_detail) +{ + ASSERT_FALSE (to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ to_string (static_cast (0)) }); + + ASSERT_FALSE (to_string (nano::log::detail::_last).empty ()); + ASSERT_NO_THROW (std::string{ to_string (nano::log::detail::_last) }); + ASSERT_EQ (to_string (nano::log::detail::_last), "_last"); +} + +TEST (enums, log_category) +{ + ASSERT_FALSE (to_string (static_cast (0)).empty ()); + ASSERT_NO_THROW (std::string{ to_string (static_cast (0)) }); + + ASSERT_FALSE (to_string (nano::log::type::_last).empty ()); + ASSERT_NO_THROW (std::string{ to_string (nano::log::type::_last) }); + ASSERT_EQ (to_string (nano::log::type::_last), "_last"); } \ No newline at end of file diff --git a/nano/core_test/frontiers_confirmation.cpp b/nano/core_test/frontiers_confirmation.cpp index 785e2b0522..08967ce4a9 100644 --- a/nano/core_test/frontiers_confirmation.cpp +++ b/nano/core_test/frontiers_confirmation.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include #include @@ -29,7 +31,7 @@ TEST (frontiers_confirmation, mode) .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } ASSERT_TIMELY_EQ (5s, node->active.size (), 1); } @@ -51,7 +53,7 @@ TEST (frontiers_confirmation, mode) .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } ASSERT_TIMELY_EQ (5s, node->active.size (), 1); } @@ -73,7 +75,7 @@ TEST (frontiers_confirmation, mode) .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); std::this_thread::sleep_for (std::chrono::seconds (1)); diff --git a/nano/core_test/gap_cache.cpp b/nano/core_test/gap_cache.cpp deleted file mode 100644 index 7b6924e396..0000000000 --- a/nano/core_test/gap_cache.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include -#include - -#include - -using namespace std::chrono_literals; - -TEST (gap_cache, add_new) -{ - nano::test::system system (1); - nano::gap_cache cache (*system.nodes[0]); - nano::block_builder builder; - auto block1 = builder - .send () - .previous (0) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (5) - .build_shared (); - cache.add (block1->hash ()); -} - -TEST (gap_cache, add_existing) -{ - nano::test::system system (1); - nano::gap_cache cache (*system.nodes[0]); - nano::block_builder builder; - auto block1 = builder - .send () - .previous (0) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (5) - .build_shared (); - cache.add (block1->hash ()); - nano::unique_lock lock{ cache.mutex }; - auto existing1 (cache.blocks.get<1> ().find (block1->hash ())); - ASSERT_NE (cache.blocks.get<1> ().end (), existing1); - auto arrival (existing1->arrival); - lock.unlock (); - ASSERT_TIMELY (20s, arrival != std::chrono::steady_clock::now ()); - cache.add (block1->hash ()); - ASSERT_EQ (1, cache.size ()); - lock.lock (); - auto existing2 (cache.blocks.get<1> ().find (block1->hash ())); - ASSERT_NE (cache.blocks.get<1> ().end (), existing2); - ASSERT_GT (existing2->arrival, arrival); -} - -TEST (gap_cache, comparison) -{ - nano::test::system system (1); - nano::gap_cache cache (*system.nodes[0]); - nano::block_builder builder; - auto block1 = builder - .send () - .previous (1) - .destination (0) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (5) - .build_shared (); - cache.add (block1->hash ()); - nano::unique_lock lock{ cache.mutex }; - auto existing1 (cache.blocks.get<1> ().find (block1->hash ())); - ASSERT_NE (cache.blocks.get<1> ().end (), existing1); - auto arrival (existing1->arrival); - lock.unlock (); - ASSERT_TIMELY (20s, std::chrono::steady_clock::now () != arrival); - auto block3 = builder - .send () - .previous (0) - .destination (42) - .balance (1) - .sign (nano::keypair ().prv, 3) - .work (4) - .build_shared (); - cache.add (block3->hash ()); - ASSERT_EQ (2, cache.size ()); - lock.lock (); - auto existing2 (cache.blocks.get<1> ().find (block3->hash ())); - ASSERT_NE (cache.blocks.get<1> ().end (), existing2); - ASSERT_GT (existing2->arrival, arrival); - ASSERT_EQ (arrival, cache.blocks.get<1> ().begin ()->arrival); -} - -// Upon receiving enough votes for a gapped block, a lazy bootstrap should be initiated -TEST (gap_cache, gap_bootstrap) -{ - nano::node_flags node_flags; - node_flags.disable_legacy_bootstrap = true; - node_flags.disable_request_loop = true; // to avoid fallback behavior of broadcasting blocks - nano::test::system system (2, nano::transport::transport_type::tcp, node_flags); - - auto & node1 (*system.nodes[0]); - auto & node2 (*system.nodes[1]); - nano::block_hash latest (node1.latest (nano::dev::genesis_key.pub)); - nano::keypair key; - nano::block_builder builder; - auto send = builder - .send () - .previous (latest) - .destination (key.pub) - .balance (nano::dev::constants.genesis_amount - 100) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send).code); - ASSERT_EQ (nano::dev::constants.genesis_amount - 100, node1.balance (nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, node2.balance (nano::dev::genesis->account ())); - // Confirm send block, allowing voting on the upcoming block - auto election = nano::test::start_election (system, node1, send->hash ()); - ASSERT_NE (nullptr, election); - election->force_confirm (); - ASSERT_TIMELY (5s, node1.block_confirmed (send->hash ())); - node1.active.erase (*send); - system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - auto latest_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, 100)); - ASSERT_NE (nullptr, latest_block); - ASSERT_TIMELY_EQ (5s, nano::dev::constants.genesis_amount - 200, node1.balance (nano::dev::genesis->account ())); - ASSERT_TIMELY_EQ (5s, nano::dev::constants.genesis_amount, node2.balance (nano::dev::genesis->account ())); - ASSERT_TIMELY_EQ (5s, node2.balance (nano::dev::genesis->account ()), nano::dev::constants.genesis_amount - 200); -} - -TEST (gap_cache, two_dependencies) -{ - nano::test::system system (1); - auto & node1 (*system.nodes[0]); - nano::keypair key; - nano::block_builder builder; - auto send1 = builder - .send () - .previous (nano::dev::genesis->hash ()) - .destination (key.pub) - .balance (1) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - auto send2 = builder - .send () - .previous (send1->hash ()) - .destination (key.pub) - .balance (0) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (send1->hash ())) - .build_shared (); - auto open = builder - .open () - .source (send1->hash ()) - .representative (key.pub) - .account (key.pub) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (0, node1.gap_cache.size ()); - node1.block_processor.add (send2); - node1.block_processor.flush (); - ASSERT_EQ (1, node1.gap_cache.size ()); - node1.block_processor.add (open); - node1.block_processor.flush (); - ASSERT_EQ (2, node1.gap_cache.size ()); - node1.block_processor.add (send1); - node1.block_processor.flush (); - ASSERT_TIMELY_EQ (5s, node1.gap_cache.size (), 0); - ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), send1->hash ())); - ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), send2->hash ())); - ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), open->hash ())); -} diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 63e8682ed3..f74d115a62 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -44,11 +46,9 @@ TEST (ledger, genesis_balance) auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = store.tx_begin_write (); - auto balance = ledger.account_balance (transaction, nano::dev::genesis->account ()); + auto balance = ledger.account_balance (transaction, nano::dev::genesis_key.pub); ASSERT_EQ (nano::dev::constants.genesis_amount, balance); - auto amount = ledger.amount (transaction, nano::dev::genesis->account ()); - ASSERT_EQ (nano::dev::constants.genesis_amount, amount); - auto info = ledger.account_info (transaction, nano::dev::genesis->account ()); + auto info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (info); ASSERT_EQ (1, ledger.cache.account_count); // Frontier time should have been updated when genesis balance was added @@ -56,7 +56,7 @@ TEST (ledger, genesis_balance) ASSERT_LT (nano::seconds_since_epoch () - info->modified, 10); // Genesis block should be confirmed by default nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (confirmation_height_info.height, 1); ASSERT_EQ (confirmation_height_info.frontier, nano::dev::genesis->hash ()); } @@ -70,16 +70,16 @@ TEST (ledger, process_modifies_sideband) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (store.tx_begin_write (), *send1).code); - ASSERT_EQ (send1->sideband ().timestamp, store.block.get (store.tx_begin_read (), send1->hash ())->sideband ().timestamp); + ASSERT_EQ (nano::block_status::progress, ledger.process (store.tx_begin_write (), send1)); + ASSERT_EQ (send1->sideband ().timestamp, ledger.block (store.tx_begin_read (), send1->hash ())->sideband ().timestamp); } // Create a send block and publish it. @@ -106,20 +106,20 @@ TEST (ledger, process_send) ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); ASSERT_EQ (1, info1->block_count); // This was a valid block, it should progress. - auto return1 = ledger.process (transaction, *send); + auto return1 = ledger.process (transaction, send); ASSERT_EQ (nano::dev::genesis_key.pub, send->sideband ().account); ASSERT_EQ (2, send->sideband ().height); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.amount (transaction, hash1)); ASSERT_TRUE (store.frontier.get (transaction, info1->head).is_zero ()); ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, hash1)); - ASSERT_EQ (nano::process_result::progress, return1.code); - ASSERT_EQ (nano::dev::genesis_key.pub, ledger.account (*send)); + ASSERT_EQ (nano::block_status::progress, return1); + ASSERT_EQ (nano::dev::genesis_key.pub, send->account ()); ASSERT_EQ (50, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.account_receivable (transaction, key2.pub)); auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (info2); ASSERT_EQ (2, info2->block_count); - auto latest6 = store.block.get (transaction, info2->head); + auto latest6 = ledger.block (transaction, info2->head); ASSERT_NE (nullptr, latest6); auto latest7 = dynamic_cast (latest6.get ()); ASSERT_NE (nullptr, latest7); @@ -135,14 +135,14 @@ TEST (ledger, process_send) .build (); nano::block_hash hash2 (open->hash ()); // This was a valid block, it should progress. - auto return2 = ledger.process (transaction, *open); - ASSERT_EQ (nano::process_result::progress, return2.code); + auto return2 = ledger.process (transaction, open); + ASSERT_EQ (nano::block_status::progress, return2); ASSERT_EQ (key2.pub, open->sideband ().account); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, open->sideband ().balance.number ()); ASSERT_EQ (1, open->sideband ().height); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.amount (transaction, hash2)); - ASSERT_EQ (nano::process_result::progress, return2.code); - ASSERT_EQ (key2.pub, ledger.account (*open)); + ASSERT_EQ (nano::block_status::progress, return2); + ASSERT_EQ (key2.pub, open->account ()); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.amount (transaction, hash2)); ASSERT_EQ (key2.pub, store.frontier.get (transaction, hash2)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.account_balance (transaction, key2.pub)); @@ -151,14 +151,14 @@ TEST (ledger, process_send) ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.weight (key2.pub)); auto info3 = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (info3); - auto latest2 = store.block.get (transaction, info3->head); + auto latest2 = ledger.block (transaction, info3->head); ASSERT_NE (nullptr, latest2); auto latest3 = dynamic_cast (latest2.get ()); ASSERT_NE (nullptr, latest3); ASSERT_EQ (*send, *latest3); auto info4 = ledger.account_info (transaction, key2.pub); ASSERT_TRUE (info4); - auto latest4 = store.block.get (transaction, info4->head); + auto latest4 = ledger.block (transaction, info4->head); ASSERT_NE (nullptr, latest4); auto latest5 = dynamic_cast (latest4.get ()); ASSERT_NE (nullptr, latest5); @@ -213,7 +213,7 @@ TEST (ledger, process_receive) .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); nano::keypair key3; auto open = builder .open () @@ -224,9 +224,9 @@ TEST (ledger, process_receive) .work (*pool.generate (key2.pub)) .build (); nano::block_hash hash2 (open->hash ()); - auto return1 = ledger.process (transaction, *open); - ASSERT_EQ (nano::process_result::progress, return1.code); - ASSERT_EQ (key2.pub, ledger.account (*open)); + auto return1 = ledger.process (transaction, open); + ASSERT_EQ (nano::block_status::progress, return1); + ASSERT_EQ (key2.pub, open->account ()); ASSERT_EQ (key2.pub, open->sideband ().account); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, open->sideband ().balance.number ()); ASSERT_EQ (1, open->sideband ().height); @@ -241,7 +241,7 @@ TEST (ledger, process_receive) .work (*pool.generate (hash1)) .build (); nano::block_hash hash3 = send2->hash (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); auto receive = builder .receive () .previous (hash2) @@ -251,15 +251,15 @@ TEST (ledger, process_receive) .build (); auto hash4 = receive->hash (); ASSERT_EQ (key2.pub, store.frontier.get (transaction, hash2)); - auto return2 = ledger.process (transaction, *receive); + auto return2 = ledger.process (transaction, receive); ASSERT_EQ (key2.pub, receive->sideband ().account); ASSERT_EQ (nano::dev::constants.genesis_amount - 25, receive->sideband ().balance.number ()); ASSERT_EQ (2, receive->sideband ().height); ASSERT_EQ (25, ledger.amount (transaction, hash4)); ASSERT_TRUE (store.frontier.get (transaction, hash2).is_zero ()); ASSERT_EQ (key2.pub, store.frontier.get (transaction, hash4)); - ASSERT_EQ (nano::process_result::progress, return2.code); - ASSERT_EQ (key2.pub, ledger.account (*receive)); + ASSERT_EQ (nano::block_status::progress, return2); + ASSERT_EQ (key2.pub, receive->account ()); ASSERT_EQ (hash4, ledger.latest (transaction, key2.pub)); ASSERT_EQ (25, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.account_receivable (transaction, key2.pub)); @@ -301,7 +301,7 @@ TEST (ledger, rollback_receiver) .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); nano::keypair key3; auto open = builder .open () @@ -312,7 +312,7 @@ TEST (ledger, rollback_receiver) .work (*pool.generate (key2.pub)) .build (); nano::block_hash hash2 (open->hash ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); ASSERT_EQ (hash2, ledger.latest (transaction, key2.pub)); ASSERT_EQ (50, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.account_balance (transaction, key2.pub)); @@ -346,7 +346,7 @@ TEST (ledger, rollback_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change1)); nano::keypair key3; auto change2 = builder .change () @@ -355,7 +355,7 @@ TEST (ledger, rollback_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (change1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change2)); nano::keypair key2; auto send1 = builder .send () @@ -365,7 +365,7 @@ TEST (ledger, rollback_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (change2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); nano::keypair key4; auto open = builder .open () @@ -375,7 +375,7 @@ TEST (ledger, rollback_representation) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); auto send2 = builder .send () .previous (send1->hash ()) @@ -384,7 +384,7 @@ TEST (ledger, rollback_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); auto receive1 = builder .receive () .previous (open->hash ()) @@ -392,7 +392,7 @@ TEST (ledger, rollback_representation) .sign (key2.prv, key2.pub) .work (*pool.generate (open->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); ASSERT_EQ (1, ledger.weight (key3.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 1, ledger.weight (key4.pub)); auto info1 = ledger.account_info (transaction, key2.pub); @@ -436,7 +436,7 @@ TEST (ledger, receive_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto receive = builder .receive () .previous (send->hash ()) @@ -444,7 +444,7 @@ TEST (ledger, receive_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); ASSERT_FALSE (ledger.rollback (transaction, receive->hash ())); } @@ -468,8 +468,8 @@ TEST (ledger, process_duplicate) .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::old, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::old, ledger.process (transaction, send)); auto open = builder .open () .source (hash1) @@ -478,8 +478,8 @@ TEST (ledger, process_duplicate) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); - ASSERT_EQ (nano::process_result::old, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); + ASSERT_EQ (nano::block_status::old, ledger.process (transaction, open)); } TEST (ledger, representative_genesis) @@ -497,7 +497,7 @@ TEST (ledger, weight) { auto ctx = nano::test::context::ledger_empty (); auto & ledger = ctx.ledger (); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); } TEST (ledger, representative_change) @@ -521,12 +521,12 @@ TEST (ledger, representative_change) .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); - auto return1 (ledger.process (transaction, *block)); + auto return1 (ledger.process (transaction, block)); ASSERT_EQ (0, ledger.amount (transaction, block->hash ())); ASSERT_TRUE (store.frontier.get (transaction, info1->head).is_zero ()); ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, block->hash ())); - ASSERT_EQ (nano::process_result::progress, return1.code); - ASSERT_EQ (nano::dev::genesis_key.pub, ledger.account (*block)); + ASSERT_EQ (nano::block_status::progress, return1); + ASSERT_EQ (nano::dev::genesis_key.pub, block->account ()); ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (key2.pub)); auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); @@ -562,7 +562,7 @@ TEST (ledger, send_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block)); auto block2 = builder .send () .previous (info1->head) @@ -571,7 +571,7 @@ TEST (ledger, send_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, block2)); } TEST (ledger, receive_fork) @@ -594,7 +594,7 @@ TEST (ledger, receive_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block)); auto block2 = builder .open () .source (block->hash ()) @@ -603,7 +603,7 @@ TEST (ledger, receive_fork) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); auto block3 = builder .change () .previous (block2->hash ()) @@ -611,7 +611,7 @@ TEST (ledger, receive_fork) .sign (key2.prv, key2.pub) .work (*pool.generate (block2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block3)); auto block4 = builder .send () .previous (block->hash ()) @@ -620,7 +620,7 @@ TEST (ledger, receive_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block4)); auto block5 = builder .receive () .previous (block2->hash ()) @@ -628,7 +628,7 @@ TEST (ledger, receive_fork) .sign (key2.prv, key2.pub) .work (*pool.generate (block2->hash ())) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block5).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, block5)); } TEST (ledger, open_fork) @@ -651,7 +651,7 @@ TEST (ledger, open_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block)); auto block2 = builder .open () .source (block->hash ()) @@ -660,7 +660,7 @@ TEST (ledger, open_fork) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); auto block3 = builder .open () .source (block->hash ()) @@ -669,7 +669,7 @@ TEST (ledger, open_fork) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block3).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, block3)); } TEST (ledger, representation_changes) @@ -702,7 +702,7 @@ TEST (ledger, representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, rep_weights.representation_get (nano::dev::genesis_key.pub)); nano::keypair key3; auto block2 = builder @@ -713,7 +713,7 @@ TEST (ledger, representation) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (100, rep_weights.representation_get (key3.pub)); @@ -725,7 +725,7 @@ TEST (ledger, representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block3)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (100, rep_weights.representation_get (key3.pub)); @@ -736,7 +736,7 @@ TEST (ledger, representation) .sign (key2.prv, key2.pub) .work (*pool.generate (block2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block4)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (200, rep_weights.representation_get (key3.pub)); @@ -748,7 +748,7 @@ TEST (ledger, representation) .sign (key2.prv, key2.pub) .work (*pool.generate (block4->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block5).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block5)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (0, rep_weights.representation_get (key3.pub)); @@ -762,7 +762,7 @@ TEST (ledger, representation) .sign (key2.prv, key2.pub) .work (*pool.generate (block5->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block6).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block6)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (0, rep_weights.representation_get (key3.pub)); @@ -777,7 +777,7 @@ TEST (ledger, representation) .sign (key5.prv, key5.pub) .work (*pool.generate (key5.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block7).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block7)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (0, rep_weights.representation_get (key3.pub)); @@ -792,7 +792,7 @@ TEST (ledger, representation) .sign (key2.prv, key2.pub) .work (*pool.generate (block6->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block8).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block8)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (0, rep_weights.representation_get (key3.pub)); @@ -806,7 +806,7 @@ TEST (ledger, representation) .sign (key5.prv, key5.pub) .work (*pool.generate (block7->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block9).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block9)); ASSERT_EQ (nano::dev::constants.genesis_amount - 200, rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, rep_weights.representation_get (key2.pub)); ASSERT_EQ (0, rep_weights.representation_get (key3.pub)); @@ -817,7 +817,7 @@ TEST (ledger, representation) TEST (ledger, double_open) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -835,7 +835,7 @@ TEST (ledger, double_open) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .open () .source (send1->hash ()) @@ -844,7 +844,7 @@ TEST (ledger, double_open) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto open2 = builder .open () .source (send1->hash ()) @@ -853,7 +853,7 @@ TEST (ledger, double_open) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *open2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, open2)); } TEST (ledger, double_receive) @@ -873,7 +873,7 @@ TEST (ledger, double_receive) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .open () .source (send1->hash ()) @@ -882,7 +882,7 @@ TEST (ledger, double_receive) .sign (key2.prv, key2.pub) .work (*pool.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto receive1 = builder .receive () .previous (open1->hash ()) @@ -890,7 +890,7 @@ TEST (ledger, double_receive) .sign (key2.prv, key2.pub) .work (*pool.generate (open1->hash ())) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, receive1)); } TEST (votes, check_signature) @@ -908,17 +908,17 @@ TEST (votes, check_signature) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); { auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); } node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_EQ (1, election1->votes ().size ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 1, 0); vote1->signature.bytes[0] ^= 1; ASSERT_EQ (nano::vote_code::invalid, node1.vote_processor.vote_blocking (vote1, std::make_shared (node1, node1))); vote1->signature.bytes[0] ^= 1; @@ -939,17 +939,17 @@ TEST (votes, add_one) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); node1.start_election (send1); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_EQ (1, election1->votes ().size ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 1, 0); ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1)); - auto vote2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 2, 0, std::vector{ send1->hash () })); + auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 2, 0); ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote2)); ASSERT_EQ (2, election1->votes ().size ()); auto votes1 (election1->votes ()); @@ -984,11 +984,11 @@ TEST (votes, add_existing) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .build (); node1.work_generate_blocking (*send1); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (node1.store.tx_begin_write (), *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (node1.store.tx_begin_write (), send1)); node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 1, 0); ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1)); // Block is already processed from vote ASSERT_TRUE (node1.active.publish (send1)); @@ -1006,7 +1006,7 @@ TEST (votes, add_existing) node1.work_generate_blocking (*send2); ASSERT_FALSE (node1.active.publish (send2)); ASSERT_TIMELY (5s, node1.active.active (*send2)); - auto vote2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 2, 0, std::vector{ send2->hash () })); + auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send2 }, nano::vote::timestamp_min * 2, 0); // Pretend we've waited the timeout auto vote_info1 = election1->get_last_vote (nano::dev::genesis_key.pub); vote_info1.time = std::chrono::steady_clock::now () - std::chrono::seconds (20); @@ -1040,14 +1040,14 @@ TEST (votes, add_old) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); node1.start_election (send1); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 2, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 2, 0); auto channel (std::make_shared (node1, node1)); node1.vote_processor.vote_blocking (vote1, channel); nano::keypair key2; @@ -1058,7 +1058,7 @@ TEST (votes, add_old) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); auto vote2 = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send2->hash () }); auto vote_info = election1->get_last_vote (nano::dev::genesis_key.pub); @@ -1090,7 +1090,7 @@ TEST (votes, DISABLED_add_old_different_account) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto send2 = builder .send () @@ -1099,10 +1099,10 @@ TEST (votes, DISABLED_add_old_different_account) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node1.process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); + ASSERT_EQ (nano::block_status::progress, node1.process (send2)); ASSERT_TRUE (nano::test::start_elections (system, node1, { send1, send2 })); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_NE (nullptr, election1); @@ -1110,13 +1110,13 @@ TEST (votes, DISABLED_add_old_different_account) ASSERT_NE (nullptr, election2); ASSERT_EQ (1, election1->votes ().size ()); ASSERT_EQ (1, election2->votes ().size ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 2, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 2, 0); auto channel (std::make_shared (node1, node1)); auto vote_result1 (node1.vote_processor.vote_blocking (vote1, channel)); ASSERT_EQ (nano::vote_code::vote, vote_result1); ASSERT_EQ (2, election1->votes ().size ()); ASSERT_EQ (1, election2->votes ().size ()); - auto vote2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send2->hash () })); + auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send2 }, nano::vote::timestamp_min * 1, 0); auto vote_result2 (node1.vote_processor.vote_blocking (vote2, channel)); ASSERT_EQ (nano::vote_code::vote, vote_result2); ASSERT_EQ (2, election1->votes ().size ()); @@ -1145,14 +1145,14 @@ TEST (votes, add_cooldown) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); node1.start_election (send1); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); - auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send1->hash () })); + auto vote1 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, nano::vote::timestamp_min * 1, 0); auto channel (std::make_shared (node1, node1)); node1.vote_processor.vote_blocking (vote1, channel); nano::keypair key2; @@ -1163,9 +1163,9 @@ TEST (votes, add_cooldown) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); - auto vote2 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 2, 0, std::vector{ send2->hash () })); + auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send2 }, nano::vote::timestamp_min * 2, 0); node1.vote_processor.vote_blocking (vote2, channel); ASSERT_EQ (2, election1->votes ().size ()); auto votes (election1->votes ()); @@ -1191,7 +1191,7 @@ TEST (ledger, successor) .build (); node1.work_generate_blocking (*send1); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); ASSERT_EQ (*send1, *node1.ledger.successor (transaction, nano::qualified_root (nano::root (0), nano::dev::genesis->hash ()))); ASSERT_EQ (*nano::dev::genesis, *node1.ledger.successor (transaction, nano::dev::genesis->qualified_root ())); ASSERT_EQ (nullptr, node1.ledger.successor (transaction, nano::qualified_root (0))); @@ -1213,10 +1213,10 @@ TEST (ledger, fail_change_old) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::progress, result1.code); - auto result2 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::old, result2.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::progress, result1); + auto result2 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::old, result2); } TEST (ledger, fail_change_gap_previous) @@ -1235,8 +1235,8 @@ TEST (ledger, fail_change_gap_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::root (1))) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::gap_previous, result1.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::gap_previous, result1); } TEST (ledger, fail_state_bad_signature) @@ -1257,8 +1257,8 @@ TEST (ledger, fail_state_bad_signature) .sign (nano::keypair ().prv, 0) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::bad_signature, result1.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::bad_signature, result1); } TEST (ledger, fail_epoch_bad_signature) @@ -1278,13 +1278,13 @@ TEST (ledger, fail_epoch_bad_signature) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); block->signature.bytes[0] ^= 1; - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::bad_signature, result1.code); // Fails epoch signature + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::bad_signature, result1); // Fails epoch signature block->signature.bytes[0] ^= 1; - auto result2 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::progress, result2.code); // Succeeds with epoch signature + auto result2 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::progress, result2); // Succeeds with epoch signature } TEST (ledger, fail_change_bad_signature) @@ -1303,8 +1303,8 @@ TEST (ledger, fail_change_bad_signature) .sign (nano::keypair ().prv, 0) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::bad_signature, result1.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::bad_signature, result1); } TEST (ledger, fail_change_fork) @@ -1323,8 +1323,8 @@ TEST (ledger, fail_change_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); nano::keypair key2; auto block2 = builder .change () @@ -1333,8 +1333,8 @@ TEST (ledger, fail_change_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::fork, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::fork, result2); } TEST (ledger, fail_send_old) @@ -1354,10 +1354,10 @@ TEST (ledger, fail_send_old) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::progress, result1.code); - auto result2 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::old, result2.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::progress, result1); + auto result2 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::old, result2); } TEST (ledger, fail_send_gap_previous) @@ -1377,8 +1377,8 @@ TEST (ledger, fail_send_gap_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::root (1))) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::gap_previous, result1.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::gap_previous, result1); } TEST (ledger, fail_send_bad_signature) @@ -1398,8 +1398,8 @@ TEST (ledger, fail_send_bad_signature) .sign (nano::keypair ().prv, 0) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block); - ASSERT_EQ (nano::process_result::bad_signature, result1.code); + auto result1 = ledger.process (transaction, block); + ASSERT_EQ (nano::block_status::bad_signature, result1); } TEST (ledger, fail_send_negative_spend) @@ -1419,7 +1419,7 @@ TEST (ledger, fail_send_negative_spend) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); nano::keypair key2; auto block2 = builder .send () @@ -1429,7 +1429,7 @@ TEST (ledger, fail_send_negative_spend) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - ASSERT_EQ (nano::process_result::negative_spend, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::negative_spend, ledger.process (transaction, block2)); } TEST (ledger, fail_send_fork) @@ -1449,7 +1449,7 @@ TEST (ledger, fail_send_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); nano::keypair key2; auto block2 = builder .send () @@ -1459,7 +1459,7 @@ TEST (ledger, fail_send_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, block2)); } TEST (ledger, fail_open_old) @@ -1479,7 +1479,7 @@ TEST (ledger, fail_open_old) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); auto block2 = builder .open () .source (block1->hash ()) @@ -1488,8 +1488,8 @@ TEST (ledger, fail_open_old) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); - ASSERT_EQ (nano::process_result::old, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); + ASSERT_EQ (nano::block_status::old, ledger.process (transaction, block2)); } TEST (ledger, fail_open_gap_source) @@ -1509,8 +1509,8 @@ TEST (ledger, fail_open_gap_source) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::gap_source, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::gap_source, result2); } TEST (ledger, fail_open_bad_signature) @@ -1530,7 +1530,7 @@ TEST (ledger, fail_open_bad_signature) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); auto block2 = builder .open () .source (block1->hash ()) @@ -1540,7 +1540,7 @@ TEST (ledger, fail_open_bad_signature) .work (*pool.generate (key1.pub)) .build (); block2->signature.clear (); - ASSERT_EQ (nano::process_result::bad_signature, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::bad_signature, ledger.process (transaction, block2)); } TEST (ledger, fail_open_fork_previous) @@ -1560,7 +1560,7 @@ TEST (ledger, fail_open_fork_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); auto block2 = builder .send () .previous (block1->hash ()) @@ -1569,7 +1569,7 @@ TEST (ledger, fail_open_fork_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); auto block3 = builder .open () .source (block1->hash ()) @@ -1578,7 +1578,7 @@ TEST (ledger, fail_open_fork_previous) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block3)); auto block4 = builder .open () .source (block2->hash ()) @@ -1587,7 +1587,7 @@ TEST (ledger, fail_open_fork_previous) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block4).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, block4)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -1608,7 +1608,7 @@ TEST (ledger, fail_open_account_mismatch) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); nano::keypair badkey; auto block2 = builder .open () @@ -1618,7 +1618,7 @@ TEST (ledger, fail_open_account_mismatch) .sign (badkey.prv, badkey.pub) .work (*pool.generate (badkey.pub)) .build (); - ASSERT_NE (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_NE (nano::block_status::progress, ledger.process (transaction, block2)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -1639,7 +1639,7 @@ TEST (ledger, fail_receive_old) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); auto block2 = builder .send () .previous (block1->hash ()) @@ -1648,7 +1648,7 @@ TEST (ledger, fail_receive_old) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); auto block3 = builder .open () .source (block1->hash ()) @@ -1657,7 +1657,7 @@ TEST (ledger, fail_receive_old) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block3)); auto block4 = builder .receive () .previous (block3->hash ()) @@ -1665,8 +1665,8 @@ TEST (ledger, fail_receive_old) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block4).code); - ASSERT_EQ (nano::process_result::old, ledger.process (transaction, *block4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block4)); + ASSERT_EQ (nano::block_status::old, ledger.process (transaction, block4)); } TEST (ledger, fail_receive_gap_source) @@ -1686,8 +1686,8 @@ TEST (ledger, fail_receive_gap_source) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1696,8 +1696,8 @@ TEST (ledger, fail_receive_gap_source) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block3 = builder .open () .source (block1->hash ()) @@ -1706,8 +1706,8 @@ TEST (ledger, fail_receive_gap_source) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::progress, result3); auto block4 = builder .receive () .previous (block3->hash ()) @@ -1715,8 +1715,8 @@ TEST (ledger, fail_receive_gap_source) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - auto result4 = ledger.process (transaction, *block4); - ASSERT_EQ (nano::process_result::gap_source, result4.code); + auto result4 = ledger.process (transaction, block4); + ASSERT_EQ (nano::block_status::gap_source, result4); } TEST (ledger, fail_receive_overreceive) @@ -1736,8 +1736,8 @@ TEST (ledger, fail_receive_overreceive) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .open () .source (block1->hash ()) @@ -1746,8 +1746,8 @@ TEST (ledger, fail_receive_overreceive) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result3); auto block3 = builder .receive () .previous (block2->hash ()) @@ -1755,8 +1755,8 @@ TEST (ledger, fail_receive_overreceive) .sign (key1.prv, key1.pub) .work (*pool.generate (block2->hash ())) .build (); - auto result4 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::unreceivable, result4.code); + auto result4 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::unreceivable, result4); } TEST (ledger, fail_receive_bad_signature) @@ -1776,8 +1776,8 @@ TEST (ledger, fail_receive_bad_signature) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1786,8 +1786,8 @@ TEST (ledger, fail_receive_bad_signature) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block3 = builder .open () .source (block1->hash ()) @@ -1796,8 +1796,8 @@ TEST (ledger, fail_receive_bad_signature) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::progress, result3); auto block4 = builder .receive () .previous (block3->hash ()) @@ -1805,8 +1805,8 @@ TEST (ledger, fail_receive_bad_signature) .sign (nano::keypair ().prv, 0) .work (*pool.generate (block3->hash ())) .build (); - auto result4 = ledger.process (transaction, *block4); - ASSERT_EQ (nano::process_result::bad_signature, result4.code); + auto result4 = ledger.process (transaction, block4); + ASSERT_EQ (nano::block_status::bad_signature, result4); } TEST (ledger, fail_receive_gap_previous_opened) @@ -1826,8 +1826,8 @@ TEST (ledger, fail_receive_gap_previous_opened) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1836,8 +1836,8 @@ TEST (ledger, fail_receive_gap_previous_opened) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block3 = builder .open () .source (block1->hash ()) @@ -1846,8 +1846,8 @@ TEST (ledger, fail_receive_gap_previous_opened) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::progress, result3); auto block4 = builder .receive () .previous (1) @@ -1855,8 +1855,8 @@ TEST (ledger, fail_receive_gap_previous_opened) .sign (key1.prv, key1.pub) .work (*pool.generate (nano::root (1))) .build (); - auto result4 = ledger.process (transaction, *block4); - ASSERT_EQ (nano::process_result::gap_previous, result4.code); + auto result4 = ledger.process (transaction, block4); + ASSERT_EQ (nano::block_status::gap_previous, result4); } TEST (ledger, fail_receive_gap_previous_unopened) @@ -1876,8 +1876,8 @@ TEST (ledger, fail_receive_gap_previous_unopened) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1886,8 +1886,8 @@ TEST (ledger, fail_receive_gap_previous_unopened) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block3 = builder .receive () .previous (1) @@ -1895,8 +1895,8 @@ TEST (ledger, fail_receive_gap_previous_unopened) .sign (key1.prv, key1.pub) .work (*pool.generate (nano::root (1))) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::gap_previous, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::gap_previous, result3); } TEST (ledger, fail_receive_fork_previous) @@ -1916,8 +1916,8 @@ TEST (ledger, fail_receive_fork_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1926,8 +1926,8 @@ TEST (ledger, fail_receive_fork_previous) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block3 = builder .open () .source (block1->hash ()) @@ -1936,8 +1936,8 @@ TEST (ledger, fail_receive_fork_previous) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::progress, result3); nano::keypair key2; auto block4 = builder .send () @@ -1947,8 +1947,8 @@ TEST (ledger, fail_receive_fork_previous) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - auto result4 = ledger.process (transaction, *block4); - ASSERT_EQ (nano::process_result::progress, result4.code); + auto result4 = ledger.process (transaction, block4); + ASSERT_EQ (nano::block_status::progress, result4); auto block5 = builder .receive () .previous (block3->hash ()) @@ -1956,8 +1956,8 @@ TEST (ledger, fail_receive_fork_previous) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - auto result5 = ledger.process (transaction, *block5); - ASSERT_EQ (nano::process_result::fork, result5.code); + auto result5 = ledger.process (transaction, block5); + ASSERT_EQ (nano::block_status::fork, result5); } TEST (ledger, fail_receive_received_source) @@ -1977,8 +1977,8 @@ TEST (ledger, fail_receive_received_source) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - auto result1 = ledger.process (transaction, *block1); - ASSERT_EQ (nano::process_result::progress, result1.code); + auto result1 = ledger.process (transaction, block1); + ASSERT_EQ (nano::block_status::progress, result1); auto block2 = builder .send () .previous (block1->hash ()) @@ -1987,8 +1987,8 @@ TEST (ledger, fail_receive_received_source) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) .build (); - auto result2 = ledger.process (transaction, *block2); - ASSERT_EQ (nano::process_result::progress, result2.code); + auto result2 = ledger.process (transaction, block2); + ASSERT_EQ (nano::block_status::progress, result2); auto block6 = builder .send () .previous (block2->hash ()) @@ -1997,8 +1997,8 @@ TEST (ledger, fail_receive_received_source) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block2->hash ())) .build (); - auto result6 = ledger.process (transaction, *block6); - ASSERT_EQ (nano::process_result::progress, result6.code); + auto result6 = ledger.process (transaction, block6); + ASSERT_EQ (nano::block_status::progress, result6); auto block3 = builder .open () .source (block1->hash ()) @@ -2007,8 +2007,8 @@ TEST (ledger, fail_receive_received_source) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto result3 = ledger.process (transaction, *block3); - ASSERT_EQ (nano::process_result::progress, result3.code); + auto result3 = ledger.process (transaction, block3); + ASSERT_EQ (nano::block_status::progress, result3); nano::keypair key2; auto block4 = builder .send () @@ -2018,8 +2018,8 @@ TEST (ledger, fail_receive_received_source) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - auto result4 = ledger.process (transaction, *block4); - ASSERT_EQ (nano::process_result::progress, result4.code); + auto result4 = ledger.process (transaction, block4); + ASSERT_EQ (nano::block_status::progress, result4); auto block5 = builder .receive () .previous (block4->hash ()) @@ -2027,8 +2027,8 @@ TEST (ledger, fail_receive_received_source) .sign (key1.prv, key1.pub) .work (*pool.generate (block4->hash ())) .build (); - auto result5 = ledger.process (transaction, *block5); - ASSERT_EQ (nano::process_result::progress, result5.code); + auto result5 = ledger.process (transaction, block5); + ASSERT_EQ (nano::block_status::progress, result5); auto block7 = builder .receive () .previous (block3->hash ()) @@ -2036,8 +2036,8 @@ TEST (ledger, fail_receive_received_source) .sign (key1.prv, key1.pub) .work (*pool.generate (block3->hash ())) .build (); - auto result7 = ledger.process (transaction, *block7); - ASSERT_EQ (nano::process_result::fork, result7.code); + auto result7 = ledger.process (transaction, block7); + ASSERT_EQ (nano::block_status::fork, result7); } TEST (ledger, latest_empty) @@ -2070,7 +2070,7 @@ TEST (ledger, latest_root) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (hash1)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); ASSERT_EQ (send->hash (), ledger.latest_root (transaction, nano::dev::genesis_key.pub).as_block_hash ()); } @@ -2092,7 +2092,7 @@ TEST (ledger, change_representative_move_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); nano::keypair key2; auto change = builder @@ -2102,7 +2102,7 @@ TEST (ledger, change_representative_move_representation) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change)); nano::keypair key3; auto open = builder .open () @@ -2112,7 +2112,7 @@ TEST (ledger, change_representative_move_representation) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (key3.pub)); } @@ -2135,8 +2135,8 @@ TEST (ledger, send_open_receive_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - auto return1 = ledger.process (transaction, *send1); - ASSERT_EQ (nano::process_result::progress, return1.code); + auto return1 = ledger.process (transaction, send1); + ASSERT_EQ (nano::block_status::progress, return1); auto send2 = builder .send () .previous (send1->hash ()) @@ -2145,8 +2145,8 @@ TEST (ledger, send_open_receive_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - auto return2 = ledger.process (transaction, *send2); - ASSERT_EQ (nano::process_result::progress, return2.code); + auto return2 = ledger.process (transaction, send2); + ASSERT_EQ (nano::block_status::progress, return2); nano::keypair key2; auto open = builder .open () @@ -2156,8 +2156,8 @@ TEST (ledger, send_open_receive_rollback) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - auto return4 = ledger.process (transaction, *open); - ASSERT_EQ (nano::process_result::progress, return4.code); + auto return4 = ledger.process (transaction, open); + ASSERT_EQ (nano::block_status::progress, return4); auto receive = builder .receive () .previous (open->hash ()) @@ -2165,8 +2165,8 @@ TEST (ledger, send_open_receive_rollback) .sign (key1.prv, key1.pub) .work (*pool.generate (open->hash ())) .build (); - auto return5 = ledger.process (transaction, *receive); - ASSERT_EQ (nano::process_result::progress, return5.code); + auto return5 = ledger.process (transaction, receive); + ASSERT_EQ (nano::block_status::progress, return5); nano::keypair key3; ASSERT_EQ (100, ledger.weight (key2.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, ledger.weight (nano::dev::genesis_key.pub)); @@ -2178,8 +2178,8 @@ TEST (ledger, send_open_receive_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send2->hash ())) .build (); - auto return6 = ledger.process (transaction, *change1); - ASSERT_EQ (nano::process_result::progress, return6.code); + auto return6 = ledger.process (transaction, change1); + ASSERT_EQ (nano::block_status::progress, return6); ASSERT_EQ (100, ledger.weight (key2.pub)); ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, ledger.weight (key3.pub)); @@ -2225,7 +2225,7 @@ TEST (ledger, bootstrap_rep_weight) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); } ASSERT_EQ (2, ledger.cache.block_count); { @@ -2246,7 +2246,7 @@ TEST (ledger, bootstrap_rep_weight) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); } ASSERT_EQ (3, ledger.cache.block_count); ASSERT_EQ (0, ledger.weight (key2.pub)); @@ -2275,7 +2275,7 @@ TEST (ledger, block_destination_source) auto block2 = builder .send () .previous (block1->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (balance) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block1->hash ())) @@ -2291,9 +2291,9 @@ TEST (ledger, block_destination_source) balance -= nano::Gxrb_ratio; auto block4 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (block3->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (balance) .link (dest.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -2302,44 +2302,44 @@ TEST (ledger, block_destination_source) balance -= nano::Gxrb_ratio; auto block5 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (block4->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (balance) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block4->hash ())) .build (); balance += nano::Gxrb_ratio; auto block6 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (block5->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (balance) .link (block5->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (block5->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block1).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block2).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block3).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block4).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block5).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block6).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block1)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block2)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block3)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block4)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block5)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, block6)); ASSERT_EQ (balance, ledger.balance (transaction, block6->hash ())); - ASSERT_EQ (dest.pub, ledger.block_destination (transaction, *block1)); - ASSERT_TRUE (ledger.block_source (transaction, *block1).is_zero ()); - ASSERT_EQ (nano::dev::genesis->account (), ledger.block_destination (transaction, *block2)); - ASSERT_TRUE (ledger.block_source (transaction, *block2).is_zero ()); - ASSERT_EQ (ledger.block_destination (transaction, *block3), nullptr); - ASSERT_EQ (block2->hash (), ledger.block_source (transaction, *block3)); - ASSERT_EQ (dest.pub, ledger.block_destination (transaction, *block4)); - ASSERT_TRUE (ledger.block_source (transaction, *block4).is_zero ()); - ASSERT_EQ (nano::dev::genesis->account (), ledger.block_destination (transaction, *block5)); - ASSERT_TRUE (ledger.block_source (transaction, *block5).is_zero ()); - ASSERT_EQ (ledger.block_destination (transaction, *block6), nullptr); - ASSERT_EQ (block5->hash (), ledger.block_source (transaction, *block6)); + ASSERT_EQ (dest.pub, block1->destination ()); + ASSERT_FALSE (block1->source_field ()); + ASSERT_EQ (nano::dev::genesis_key.pub, block2->destination ()); + ASSERT_FALSE (block2->source_field ()); + ASSERT_FALSE (block3->destination_field ()); + ASSERT_EQ (block2->hash (), block3->source ()); + ASSERT_EQ (dest.pub, block4->destination ()); + ASSERT_FALSE (block4->source_field ()); + ASSERT_EQ (nano::dev::genesis_key.pub, block5->destination ()); + ASSERT_FALSE (block5->source_field ()); + ASSERT_FALSE (block6->destination_field ()); + ASSERT_EQ (block5->hash (), block6->source ()); } TEST (ledger, state_account) @@ -2352,16 +2352,16 @@ TEST (ledger, state_account) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::dev::genesis->account (), ledger.account (transaction, send1->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_EQ (nano::dev::genesis_key.pub, ledger.account (transaction, send1->hash ())); } TEST (ledger, state_send_receive) @@ -2374,50 +2374,50 @@ TEST (ledger, state_send_receive) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); - ASSERT_TRUE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); + ASSERT_TRUE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (2, send2->sideband ().height); - ASSERT_TRUE (send2->sideband ().details.is_send); - ASSERT_FALSE (send2->sideband ().details.is_receive); + ASSERT_TRUE (send2->is_send ()); + ASSERT_FALSE (send2->is_receive ()); ASSERT_FALSE (send2->sideband ().details.is_epoch); auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_TRUE (store.block.exists (transaction, receive1->hash ())); - auto receive2 = store.block.get (transaction, receive1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_TRUE (ledger.block_exists (transaction, receive1->hash ())); + auto receive2 = ledger.block (transaction, receive1->hash ()); ASSERT_NE (nullptr, receive2); ASSERT_EQ (*receive1, *receive2); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.balance (transaction, receive1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); - ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); + ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); ASSERT_EQ (3, receive2->sideband ().height); - ASSERT_FALSE (receive2->sideband ().details.is_send); - ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->is_send ()); + ASSERT_TRUE (receive2->is_receive ()); ASSERT_FALSE (receive2->sideband ().details.is_epoch); } @@ -2432,40 +2432,40 @@ TEST (ledger, state_receive) auto send1 = builder .send () .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_TRUE (store.block.exists (transaction, receive1->hash ())); - auto receive2 = store.block.get (transaction, receive1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_TRUE (ledger.block_exists (transaction, receive1->hash ())); + auto receive2 = ledger.block (transaction, receive1->hash ()); ASSERT_NE (nullptr, receive2); ASSERT_EQ (*receive1, *receive2); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.balance (transaction, receive1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (3, receive2->sideband ().height); - ASSERT_FALSE (receive2->sideband ().details.is_send); - ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->is_send ()); + ASSERT_TRUE (receive2->is_receive ()); ASSERT_FALSE (receive2->sideband ().details.is_epoch); } @@ -2480,7 +2480,7 @@ TEST (ledger, state_rep_change) nano::block_builder builder; auto change1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount) @@ -2488,18 +2488,18 @@ TEST (ledger, state_rep_change) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change1).code); - ASSERT_TRUE (store.block.exists (transaction, change1->hash ())); - auto change2 = store.block.get (transaction, change1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change1)); + ASSERT_TRUE (ledger.block_exists (transaction, change1->hash ())); + auto change2 = ledger.block (transaction, change1->hash ()); ASSERT_NE (nullptr, change2); ASSERT_EQ (*change1, *change2); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.balance (transaction, change1->hash ())); ASSERT_EQ (0, ledger.amount (transaction, change1->hash ())); - ASSERT_EQ (0, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (rep.pub)); ASSERT_EQ (2, change2->sideband ().height); - ASSERT_FALSE (change2->sideband ().details.is_send); - ASSERT_FALSE (change2->sideband ().details.is_receive); + ASSERT_FALSE (change2->is_send ()); + ASSERT_FALSE (change2->is_receive ()); ASSERT_FALSE (change2->sideband ().details.is_epoch); } @@ -2514,46 +2514,46 @@ TEST (ledger, state_open) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_TRUE (store.pending.exists (transaction, nano::pending_key (destination.pub, send1->hash ()))); auto open1 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (destination.pub, send1->hash ()))); - ASSERT_TRUE (store.block.exists (transaction, open1->hash ())); - auto open2 = store.block.get (transaction, open1->hash ()); + ASSERT_TRUE (ledger.block_exists (transaction, open1->hash ())); + auto open2 = ledger.block (transaction, open1->hash ()); ASSERT_NE (nullptr, open2); ASSERT_EQ (*open1, *open2); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, open1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, open1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (ledger.cache.account_count, store.account.count (transaction)); ASSERT_EQ (1, open2->sideband ().height); - ASSERT_FALSE (open2->sideband ().details.is_send); - ASSERT_TRUE (open2->sideband ().details.is_receive); + ASSERT_FALSE (open2->is_send ()); + ASSERT_TRUE (open2->is_receive ()); ASSERT_FALSE (open2->sideband ().details.is_epoch); } @@ -2568,24 +2568,24 @@ TEST (ledger, send_after_state_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto send2 = builder .send () .previous (send1->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - (2 * nano::Gxrb_ratio)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, send2)); } // Make sure old block types can't be inserted after a state block. @@ -2599,15 +2599,15 @@ TEST (ledger, receive_after_state_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto receive1 = builder .receive () .previous (send1->hash ()) @@ -2615,7 +2615,7 @@ TEST (ledger, receive_after_state_fail) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, receive1)); } // Make sure old block types can't be inserted after a state block. @@ -2629,15 +2629,15 @@ TEST (ledger, change_after_state_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); nano::keypair rep; auto change1 = builder .change () @@ -2646,7 +2646,7 @@ TEST (ledger, change_after_state_fail) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, change1)); } TEST (ledger, state_unreceivable_fail) @@ -2660,30 +2660,30 @@ TEST (ledger, state_unreceivable_fail) auto send1 = builder .send () .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::gap_source, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::gap_source, ledger.process (transaction, receive1)); } TEST (ledger, state_receive_bad_amount_fail) @@ -2697,30 +2697,30 @@ TEST (ledger, state_receive_bad_amount_fail) auto send1 = builder .send () .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::balance_mismatch, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::balance_mismatch, ledger.process (transaction, receive1)); } TEST (ledger, state_no_link_amount_fail) @@ -2733,19 +2733,19 @@ TEST (ledger, state_no_link_amount_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); nano::keypair rep; auto change1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount) @@ -2753,7 +2753,7 @@ TEST (ledger, state_no_link_amount_fail) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::balance_mismatch, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::balance_mismatch, ledger.process (transaction, change1)); } TEST (ledger, state_receive_wrong_account_fail) @@ -2766,34 +2766,34 @@ TEST (ledger, state_receive_wrong_account_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); nano::keypair key; auto receive1 = builder .state () .account (key.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (key.prv, key.pub) .work (*pool.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, receive1)); } TEST (ledger, state_open_state_fork) @@ -2807,35 +2807,35 @@ TEST (ledger, state_open_state_fork) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto open2 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *open2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, open2)); ASSERT_EQ (open1->root (), open2->root ()); } @@ -2850,35 +2850,35 @@ TEST (ledger, state_state_open_fork) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto open2 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *open2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, open2)); ASSERT_EQ (open1->root (), open2->root ()); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -2894,26 +2894,26 @@ TEST (ledger, state_open_previous_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .state () .account (destination.pub) .previous (1) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (*pool.generate (1)) .build (); - ASSERT_EQ (nano::process_result::gap_previous, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::gap_previous, ledger.process (transaction, open1)); } TEST (ledger, state_open_source_fail) @@ -2927,26 +2927,26 @@ TEST (ledger, state_open_source_fail) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (0) .link (0) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::gap_source, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::gap_source, ledger.process (transaction, open1)); } TEST (ledger, state_send_change) @@ -2960,26 +2960,26 @@ TEST (ledger, state_send_change) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (0, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (rep.pub)); ASSERT_EQ (2, send2->sideband ().height); - ASSERT_TRUE (send2->sideband ().details.is_send); - ASSERT_FALSE (send2->sideband ().details.is_receive); + ASSERT_TRUE (send2->is_send ()); + ASSERT_FALSE (send2->is_receive ()); ASSERT_FALSE (send2->sideband ().details.is_epoch); } @@ -2993,26 +2993,26 @@ TEST (ledger, state_receive_change) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); nano::keypair rep; auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount) @@ -3020,18 +3020,18 @@ TEST (ledger, state_receive_change) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_TRUE (store.block.exists (transaction, receive1->hash ())); - auto receive2 = store.block.get (transaction, receive1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_TRUE (ledger.block_exists (transaction, receive1->hash ())); + auto receive2 = ledger.block (transaction, receive1->hash ()); ASSERT_NE (nullptr, receive2); ASSERT_EQ (*receive1, *receive2); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.balance (transaction, receive1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1->hash ())); - ASSERT_EQ (0, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (rep.pub)); ASSERT_EQ (3, receive2->sideband ().height); - ASSERT_FALSE (receive2->sideband ().details.is_send); - ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->is_send ()); + ASSERT_TRUE (receive2->is_receive ()); ASSERT_FALSE (receive2->sideband ().details.is_epoch); } @@ -3046,27 +3046,27 @@ TEST (ledger, state_open_old) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, open1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, open1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); } TEST (ledger, state_receive_old) @@ -3080,35 +3080,35 @@ TEST (ledger, state_receive_old) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - (2 * nano::Gxrb_ratio)) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto receive1 = builder .receive () .previous (open1->hash ()) @@ -3116,10 +3116,10 @@ TEST (ledger, state_receive_old) .sign (destination.prv, destination.pub) .work (*pool.generate (open1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); ASSERT_EQ (2 * nano::Gxrb_ratio, ledger.balance (transaction, receive1->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); } TEST (ledger, state_rollback_send) @@ -3132,30 +3132,30 @@ TEST (ledger, state_rollback_send) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store.block.exists (transaction, send1->hash ())); - auto send2 = store.block.get (transaction, send1->hash ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (ledger.block_exists (transaction, send1->hash ())); + auto send2 = ledger.block (transaction, send1->hash ()); ASSERT_NE (nullptr, send2); ASSERT_EQ (*send1, *send2); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); - auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); + auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info); - ASSERT_EQ (nano::dev::genesis->account (), info->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info->source); ASSERT_EQ (nano::Gxrb_ratio, info->amount.number ()); ASSERT_FALSE (ledger.rollback (transaction, send1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); - ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_FALSE (ledger.block_exists (transaction, send1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); + ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_TRUE (store.block.successor (transaction, nano::dev::genesis->hash ()).is_zero ()); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -3170,35 +3170,35 @@ TEST (ledger, state_rollback_receive) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), receive1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, receive1->hash ()))); ASSERT_FALSE (ledger.rollback (transaction, receive1->hash ())); - auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info); - ASSERT_EQ (nano::dev::genesis->account (), info->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info->source); ASSERT_EQ (nano::Gxrb_ratio, info->amount.number ()); - ASSERT_FALSE (store.block.exists (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_FALSE (ledger.block_exists (transaction, receive1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -3213,15 +3213,15 @@ TEST (ledger, state_rollback_received_send) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto receive1 = builder .state () .account (key.pub) @@ -3232,14 +3232,14 @@ TEST (ledger, state_rollback_received_send) .sign (key.prv, key.pub) .work (*pool.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), receive1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, receive1->hash ()))); ASSERT_FALSE (ledger.rollback (transaction, send1->hash ())); - ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); - ASSERT_FALSE (store.block.exists (transaction, send1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_FALSE (store.pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); + ASSERT_FALSE (ledger.block_exists (transaction, send1->hash ())); + ASSERT_FALSE (ledger.block_exists (transaction, receive1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.account_balance (transaction, key.pub)); ASSERT_EQ (0, ledger.weight (key.pub)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); @@ -3256,7 +3256,7 @@ TEST (ledger, state_rep_change_rollback) nano::block_builder builder; auto change1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount) @@ -3264,11 +3264,11 @@ TEST (ledger, state_rep_change_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change1)); ASSERT_FALSE (ledger.rollback (transaction, change1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, change1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_FALSE (ledger.block_exists (transaction, change1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (rep.pub)); } @@ -3283,33 +3283,33 @@ TEST (ledger, state_open_rollback) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto open1 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::Gxrb_ratio) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_FALSE (ledger.rollback (transaction, open1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, open1->hash ())); + ASSERT_FALSE (ledger.block_exists (transaction, open1->hash ())); ASSERT_EQ (0, ledger.account_balance (transaction, destination.pub)); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); auto info = ledger.pending_info (transaction, nano::pending_key (destination.pub, send1->hash ())); ASSERT_TRUE (info); - ASSERT_EQ (nano::dev::genesis->account (), info->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info->source); ASSERT_EQ (nano::Gxrb_ratio, info->amount.number ()); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -3325,19 +3325,19 @@ TEST (ledger, state_send_change_rollback) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_FALSE (ledger.rollback (transaction, send1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, send1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis->account ())); + ASSERT_FALSE (ledger.block_exists (transaction, send1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (rep.pub)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -3352,19 +3352,19 @@ TEST (ledger, state_receive_change_rollback) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); nano::keypair rep; auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) .representative (rep.pub) .balance (nano::dev::constants.genesis_amount) @@ -3372,11 +3372,11 @@ TEST (ledger, state_receive_change_rollback) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); ASSERT_FALSE (ledger.rollback (transaction, receive1->hash ())); - ASSERT_FALSE (store.block.exists (transaction, receive1->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis->account ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_FALSE (ledger.block_exists (transaction, receive1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (rep.pub)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); } @@ -3392,91 +3392,91 @@ TEST (ledger, epoch_blocks_v1_general) nano::block_builder builder; auto epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - ASSERT_FALSE (epoch1->sideband ().details.is_send); - ASSERT_FALSE (epoch1->sideband ().details.is_receive); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); + ASSERT_FALSE (epoch1->is_send ()); + ASSERT_FALSE (epoch1->is_receive ()); ASSERT_TRUE (epoch1->sideband ().details.is_epoch); ASSERT_EQ (nano::epoch::epoch_1, epoch1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch1->sideband ().source_epoch); // Not used for epoch blocks auto epoch2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *epoch2).code); - auto genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, epoch2)); + auto genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); ASSERT_FALSE (ledger.rollback (transaction, epoch1->hash ())); - genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_0); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); + genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); - ASSERT_FALSE (epoch1->sideband ().details.is_send); - ASSERT_FALSE (epoch1->sideband ().details.is_receive); + ASSERT_FALSE (epoch1->is_send ()); + ASSERT_FALSE (epoch1->is_receive ()); ASSERT_TRUE (epoch1->sideband ().details.is_epoch); ASSERT_EQ (nano::epoch::epoch_1, epoch1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch1->sideband ().source_epoch); // Not used for epoch blocks auto change1 = builder .change () .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, change1)); auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (send1->sideband ().details.is_send); - ASSERT_FALSE (send1->sideband ().details.is_receive); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (send1->is_send ()); + ASSERT_FALSE (send1->is_receive ()); ASSERT_FALSE (send1->sideband ().details.is_epoch); ASSERT_EQ (nano::epoch::epoch_1, send1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, send1->sideband ().source_epoch); // Not used for send blocks auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, open1)); auto epoch3 = builder .state () .account (destination.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (0) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::representative_mismatch, ledger.process (transaction, *epoch3).code); + ASSERT_EQ (nano::block_status::representative_mismatch, ledger.process (transaction, epoch3)); auto epoch4 = builder .state () .account (destination.pub) @@ -3487,9 +3487,9 @@ TEST (ledger, epoch_blocks_v1_general) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch4).code); - ASSERT_FALSE (epoch4->sideband ().details.is_send); - ASSERT_FALSE (epoch4->sideband ().details.is_receive); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch4)); + ASSERT_FALSE (epoch4->is_send ()); + ASSERT_FALSE (epoch4->is_receive ()); ASSERT_TRUE (epoch4->sideband ().details.is_epoch); ASSERT_EQ (nano::epoch::epoch_1, epoch4->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch4->sideband ().source_epoch); // Not used for epoch blocks @@ -3500,7 +3500,7 @@ TEST (ledger, epoch_blocks_v1_general) .sign (destination.prv, destination.pub) .work (*pool.generate (epoch4->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, receive1)); auto receive2 = builder .state () .account (destination.pub) @@ -3511,16 +3511,16 @@ TEST (ledger, epoch_blocks_v1_general) .sign (destination.prv, destination.pub) .work (*pool.generate (epoch4->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2)); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); ASSERT_EQ (0, ledger.balance (transaction, epoch4->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::Gxrb_ratio, ledger.weight (destination.pub)); - ASSERT_FALSE (receive2->sideband ().details.is_send); - ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->is_send ()); + ASSERT_TRUE (receive2->is_receive ()); ASSERT_FALSE (receive2->sideband ().details.is_epoch); } @@ -3535,95 +3535,95 @@ TEST (ledger, epoch_blocks_v2_general) nano::block_builder builder; auto epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); // Trying to upgrade from epoch 0 to epoch 2. It is a requirement epoch upgrades are sequential unless the account is unopened - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, epoch1)); // Set it to the first epoch and it should now succeed epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (epoch1->work) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); ASSERT_EQ (nano::epoch::epoch_1, epoch1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch1->sideband ().source_epoch); // Not used for epoch blocks auto epoch2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch2)); ASSERT_EQ (nano::epoch::epoch_2, epoch2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch2->sideband ().source_epoch); // Not used for epoch blocks auto epoch3 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch2->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *epoch3).code); - auto genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, epoch3)); + auto genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_2); ASSERT_FALSE (ledger.rollback (transaction, epoch1->hash ())); - genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_0); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); + genesis_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (genesis_info); ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); auto change1 = builder .change () .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, change1)); auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_EQ (nano::epoch::epoch_1, send1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, send1->sideband ().source_epoch); // Not used for send blocks auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (destination.pub) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, open1)); auto epoch4 = builder .state () .account (destination.pub) @@ -3634,20 +3634,20 @@ TEST (ledger, epoch_blocks_v2_general) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch4)); ASSERT_EQ (nano::epoch::epoch_1, epoch4->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch4->sideband ().source_epoch); // Not used for epoch blocks auto epoch5 = builder .state () .account (destination.pub) .previous (epoch4->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (0) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch4->hash ())) .build (); - ASSERT_EQ (nano::process_result::representative_mismatch, ledger.process (transaction, *epoch5).code); + ASSERT_EQ (nano::block_status::representative_mismatch, ledger.process (transaction, epoch5)); auto epoch6 = builder .state () .account (destination.pub) @@ -3658,7 +3658,7 @@ TEST (ledger, epoch_blocks_v2_general) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch4->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch6).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch6)); ASSERT_EQ (nano::epoch::epoch_2, epoch6->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch6->sideband ().source_epoch); // Not used for epoch blocks auto receive1 = builder @@ -3668,7 +3668,7 @@ TEST (ledger, epoch_blocks_v2_general) .sign (destination.prv, destination.pub) .work (*pool.generate (epoch6->hash ())) .build (); - ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::block_position, ledger.process (transaction, receive1)); auto receive2 = builder .state () .account (destination.pub) @@ -3679,13 +3679,13 @@ TEST (ledger, epoch_blocks_v2_general) .sign (destination.prv, destination.pub) .work (*pool.generate (epoch6->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2)); ASSERT_EQ (nano::epoch::epoch_2, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); ASSERT_EQ (0, ledger.balance (transaction, epoch6->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2->hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2->hash ())); - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::Gxrb_ratio, ledger.weight (destination.pub)); } @@ -3700,37 +3700,37 @@ TEST (ledger, epoch_blocks_receive_upgrade) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_EQ (nano::epoch::epoch_1, send2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, send2->sideband ().source_epoch); // Not used for send blocks auto open1 = builder @@ -3741,7 +3741,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination.prv, destination.pub) .work (*pool.generate (destination.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_EQ (nano::epoch::epoch_0, open1->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, open1->sideband ().source_epoch); auto receive1 = builder @@ -3751,7 +3751,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination.prv, destination.pub) .work (*pool.generate (open1->hash ())) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, receive1)); auto receive2 = builder .state () .account (destination.pub) @@ -3762,7 +3762,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination.prv, destination.pub) .work (*pool.generate (open1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2)); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); auto destination_info = ledger.account_info (transaction, destination.pub); @@ -3777,7 +3777,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) ASSERT_EQ (nano::dev::genesis_key.pub, pending_send2->source); ASSERT_EQ (nano::Gxrb_ratio, pending_send2->amount.number ()); ASSERT_EQ (nano::epoch::epoch_1, pending_send2->epoch); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2)); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); destination_info = ledger.account_info (transaction, destination.pub); @@ -3794,7 +3794,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination.prv, destination.pub) .work (*pool.generate (receive2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send3)); auto open2 = builder .open () .source (send3->hash ()) @@ -3803,31 +3803,31 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination2.prv, destination2.pub) .work (*pool.generate (destination2.pub)) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *open2).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, open2)); // Upgrade to epoch 2 and send to destination. Try to create an open block from an epoch 2 source block. nano::keypair destination3; auto epoch2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch2)); auto send4 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 3) .link (destination3.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send4)); auto open3 = builder .open () .source (send4->hash ()) @@ -3836,19 +3836,19 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination3.prv, destination3.pub) .work (*pool.generate (destination3.pub)) .build (); - ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, *open3).code); + ASSERT_EQ (nano::block_status::unreceivable, ledger.process (transaction, open3)); // Send it to an epoch 1 account auto send5 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send4->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 4) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send4->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send5).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send5)); destination_info = ledger.account_info (transaction, destination.pub); ASSERT_TRUE (destination_info); ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_1); @@ -3862,7 +3862,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (destination.prv, destination.pub) .work (*pool.generate (send3->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive3)); ASSERT_EQ (nano::epoch::epoch_2, receive3->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_2, receive3->sideband ().source_epoch); destination_info = ledger.account_info (transaction, destination.pub); @@ -3872,15 +3872,15 @@ TEST (ledger, epoch_blocks_receive_upgrade) nano::keypair destination4; auto send6 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send5->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 5) .link (destination4.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send5->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send6).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send6)); auto epoch4 = builder .state () .account (destination4.pub) @@ -3891,7 +3891,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (destination4.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch4).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch4)); ASSERT_EQ (nano::epoch::epoch_2, epoch4->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch4->sideband ().source_epoch); // Not used for epoch blocks ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); @@ -3914,53 +3914,53 @@ TEST (ledger, epoch_blocks_fork) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, epoch1)); auto epoch2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *epoch2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, epoch2)); auto epoch3 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch3)); ASSERT_EQ (nano::epoch::epoch_1, epoch3->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, epoch3->sideband ().source_epoch); // Not used for epoch state blocks auto epoch4 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *epoch2).code); + ASSERT_EQ (nano::block_status::fork, ledger.process (transaction, epoch2)); } TEST (ledger, successor_epoch) @@ -4018,11 +4018,11 @@ TEST (ledger, successor_epoch) .work (*pool.generate (open->hash ())) .build (); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *open).code); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *change).code); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send2).code); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *epoch_open).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, open)); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, change)); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, send2)); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, epoch_open)); ASSERT_EQ (*change, *node1.ledger.successor (transaction, change->qualified_root ())); ASSERT_EQ (*epoch_open, *node1.ledger.successor (transaction, epoch_open->qualified_root ())); ASSERT_EQ (nano::epoch::epoch_1, epoch_open->sideband ().details.epoch); @@ -4044,27 +4044,27 @@ TEST (ledger, epoch_open_pending) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (key1.pub)) - .build_shared (); - auto process_result = node1.ledger.process (node1.store.tx_begin_write (), *epoch_open); - ASSERT_EQ (nano::process_result::gap_epoch_open_pending, process_result.code); + .build (); + auto process_result = node1.ledger.process (node1.store.tx_begin_write (), epoch_open); + ASSERT_EQ (nano::block_status::gap_epoch_open_pending, process_result); node1.block_processor.add (epoch_open); // Waits for the block to get saved in the database ASSERT_TIMELY_EQ (10s, 1, node1.unchecked.count ()); ASSERT_FALSE (node1.ledger.block_or_pruned_exists (epoch_open->hash ())); // Open block should be inserted into unchecked - auto blocks = node1.unchecked.get (nano::hash_or_account (epoch_open->account ()).hash); + auto blocks = node1.unchecked.get (nano::hash_or_account (epoch_open->account_field ().value ()).hash); ASSERT_EQ (blocks.size (), 1); ASSERT_EQ (blocks[0].block->full_hash (), epoch_open->full_hash ()); // New block to process epoch open auto send1 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.block_processor.add (send1); ASSERT_TIMELY (10s, node1.ledger.block_or_pruned_exists (epoch_open->hash ())); } @@ -4083,24 +4083,24 @@ TEST (ledger, block_hash_account_conflict) * in the ledger and not an account */ auto send1 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto receive1 = builder.state () .account (key1.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (100) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) - .build_shared (); + .build (); /* * Note that the below link is a block hash when this is intended @@ -4111,12 +4111,12 @@ TEST (ledger, block_hash_account_conflict) auto send2 = builder.state () .account (key1.pub) .previous (receive1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (90) .link (receive1->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (receive1->hash ())) - .build_shared (); + .build (); /* * Generate an epoch open for the account with the same value as the block hash @@ -4130,16 +4130,16 @@ TEST (ledger, block_hash_account_conflict) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (receive1->hash ())) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); node1.work_generate_blocking (*receive1); node1.work_generate_blocking (*send2); node1.work_generate_blocking (*open_epoch1); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node1.process (*receive1).code); - ASSERT_EQ (nano::process_result::progress, node1.process (*send2).code); - ASSERT_EQ (nano::process_result::progress, node1.process (*open_epoch1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); + ASSERT_EQ (nano::block_status::progress, node1.process (receive1)); + ASSERT_EQ (nano::block_status::progress, node1.process (send2)); + ASSERT_EQ (nano::block_status::progress, node1.process (open_epoch1)); ASSERT_TRUE (nano::test::start_elections (system, node1, { send1, receive1, send2, open_epoch1 })); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_NE (nullptr, election1); @@ -4159,148 +4159,6 @@ TEST (ledger, block_hash_account_conflict) ASSERT_EQ (*open_epoch1, *winner4); } -TEST (ledger, could_fit) -{ - nano::logger_mt logger; - auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); - ASSERT_TRUE (!store->init_error ()); - nano::stats stats; - nano::ledger ledger (*store, stats, nano::dev::constants); - auto transaction (store->tx_begin_write ()); - store->initialize (transaction, ledger.cache, ledger.constants); - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::keypair destination; - // Test legacy and state change blocks could_fit - nano::block_builder builder; - auto change1 = builder - .change () - .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - auto change2 = builder - .state () - .account (nano::dev::genesis->account ()) - .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) - .balance (nano::dev::constants.genesis_amount) - .link (0) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - ASSERT_TRUE (ledger.could_fit (transaction, *change1)); - ASSERT_TRUE (ledger.could_fit (transaction, *change2)); - // Test legacy and state send - nano::keypair key1; - auto send1 = builder - .send () - .previous (change1->hash ()) - .destination (key1.pub) - .balance (nano::dev::constants.genesis_amount - 1) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (change1->hash ())) - .build (); - auto send2 = builder - .state () - .account (nano::dev::genesis->account ()) - .previous (change1->hash ()) - .representative (nano::dev::genesis->account ()) - .balance (nano::dev::constants.genesis_amount - 1) - .link (key1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (change1->hash ())) - .build (); - ASSERT_FALSE (ledger.could_fit (transaction, *send1)); - ASSERT_FALSE (ledger.could_fit (transaction, *send2)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change1).code); - ASSERT_TRUE (ledger.could_fit (transaction, *change1)); - ASSERT_TRUE (ledger.could_fit (transaction, *change2)); - ASSERT_TRUE (ledger.could_fit (transaction, *send1)); - ASSERT_TRUE (ledger.could_fit (transaction, *send2)); - // Test legacy and state open - auto open1 = builder - .open () - .source (send2->hash ()) - .representative (nano::dev::genesis->account ()) - .account (key1.pub) - .sign (key1.prv, key1.pub) - .work (*pool.generate (key1.pub)) - .build (); - auto open2 = builder - .state () - .account (key1.pub) - .previous (0) - .representative (nano::dev::genesis->account ()) - .balance (1) - .link (send2->hash ()) - .sign (key1.prv, key1.pub) - .work (*pool.generate (key1.pub)) - .build (); - ASSERT_FALSE (ledger.could_fit (transaction, *open1)); - ASSERT_FALSE (ledger.could_fit (transaction, *open2)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); - ASSERT_TRUE (ledger.could_fit (transaction, *send1)); - ASSERT_TRUE (ledger.could_fit (transaction, *send2)); - ASSERT_TRUE (ledger.could_fit (transaction, *open1)); - ASSERT_TRUE (ledger.could_fit (transaction, *open2)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); - ASSERT_TRUE (ledger.could_fit (transaction, *open1)); - ASSERT_TRUE (ledger.could_fit (transaction, *open2)); - // Create another send to receive - auto send3 = builder - .state () - .account (nano::dev::genesis->account ()) - .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) - .balance (nano::dev::constants.genesis_amount - 2) - .link (key1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (send2->hash ())) - .build (); - // Test legacy and state receive - auto receive1 = builder - .receive () - .previous (open1->hash ()) - .source (send3->hash ()) - .sign (key1.prv, key1.pub) - .work (*pool.generate (open1->hash ())) - .build (); - auto receive2 = builder - .state () - .account (key1.pub) - .previous (open1->hash ()) - .representative (nano::dev::genesis->account ()) - .balance (2) - .link (send3->hash ()) - .sign (key1.prv, key1.pub) - .work (*pool.generate (open1->hash ())) - .build (); - ASSERT_FALSE (ledger.could_fit (transaction, *receive1)); - ASSERT_FALSE (ledger.could_fit (transaction, *receive2)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send3).code); - ASSERT_TRUE (ledger.could_fit (transaction, *receive1)); - ASSERT_TRUE (ledger.could_fit (transaction, *receive2)); - // Test epoch (state) - auto epoch1 = builder - .state () - .account (key1.pub) - .previous (receive1->hash ()) - .representative (nano::dev::genesis->account ()) - .balance (2) - .link (ledger.epoch_link (nano::epoch::epoch_1)) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (receive1->hash ())) - .build (); - ASSERT_FALSE (ledger.could_fit (transaction, *epoch1)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_TRUE (ledger.could_fit (transaction, *receive1)); - ASSERT_TRUE (ledger.could_fit (transaction, *receive2)); - ASSERT_TRUE (ledger.could_fit (transaction, *epoch1)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - ASSERT_TRUE (ledger.could_fit (transaction, *epoch1)); -} - TEST (ledger, unchecked_epoch) { nano::test::system system (1); @@ -4309,14 +4167,14 @@ TEST (ledger, unchecked_epoch) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto open1 = builder .state () @@ -4327,7 +4185,7 @@ TEST (ledger, unchecked_epoch) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open1); auto epoch1 = builder .state () @@ -4338,7 +4196,7 @@ TEST (ledger, unchecked_epoch) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*epoch1); node1.block_processor.add (epoch1); { @@ -4349,7 +4207,7 @@ TEST (ledger, unchecked_epoch) } node1.block_processor.add (send1); node1.block_processor.add (open1); - ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), epoch1->hash ())); + ASSERT_TIMELY (5s, node1.ledger.block_exists (node1.store.tx_begin_read (), epoch1->hash ())); { // Waits for the last blocks to pass through block_processor and unchecked.put queues ASSERT_TIMELY_EQ (10s, 0, node1.unchecked.count ()); @@ -4369,14 +4227,14 @@ TEST (ledger, unchecked_epoch_invalid) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto open1 = builder .state () @@ -4387,7 +4245,7 @@ TEST (ledger, unchecked_epoch_invalid) .link (send1->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open1); // Epoch block with account own signature auto epoch1 = builder @@ -4399,7 +4257,7 @@ TEST (ledger, unchecked_epoch_invalid) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*epoch1); // Pseudo epoch block (send subtype, destination - epoch link) auto epoch2 = builder @@ -4411,7 +4269,7 @@ TEST (ledger, unchecked_epoch_invalid) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*epoch2); node1.block_processor.add (epoch1); node1.block_processor.add (epoch2); @@ -4424,22 +4282,22 @@ TEST (ledger, unchecked_epoch_invalid) node1.block_processor.add (send1); node1.block_processor.add (open1); // Waits for the last blocks to pass through block_processor and unchecked.put queues - ASSERT_TIMELY (10s, node1.store.block.exists (node1.store.tx_begin_read (), epoch2->hash ())); + ASSERT_TIMELY (10s, node1.ledger.block_exists (node1.store.tx_begin_read (), epoch2->hash ())); { auto transaction = node1.store.tx_begin_read (); - ASSERT_FALSE (node1.store.block.exists (transaction, epoch1->hash ())); + ASSERT_FALSE (node1.ledger.block_exists (transaction, epoch1->hash ())); auto unchecked_count = node1.unchecked.count (); ASSERT_EQ (unchecked_count, 0); ASSERT_EQ (unchecked_count, node1.unchecked.count ()); auto info = node1.ledger.account_info (transaction, destination.pub); ASSERT_TRUE (info); ASSERT_NE (info->epoch (), nano::epoch::epoch_1); - auto epoch2_store = node1.store.block.get (transaction, epoch2->hash ()); + auto epoch2_store = node1.ledger.block (transaction, epoch2->hash ()); ASSERT_NE (nullptr, epoch2_store); ASSERT_EQ (nano::epoch::epoch_0, epoch2_store->sideband ().details.epoch); - ASSERT_TRUE (epoch2_store->sideband ().details.is_send); + ASSERT_TRUE (epoch2_store->is_send ()); ASSERT_FALSE (epoch2_store->sideband ().details.is_epoch); - ASSERT_FALSE (epoch2_store->sideband ().details.is_receive); + ASSERT_FALSE (epoch2_store->is_receive ()); } } @@ -4451,14 +4309,14 @@ TEST (ledger, unchecked_open) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto open1 = builder .open () @@ -4467,7 +4325,7 @@ TEST (ledger, unchecked_open) .account (destination.pub) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open1); // Invalid signature for open block auto open2 = builder @@ -4477,7 +4335,7 @@ TEST (ledger, unchecked_open) .account (destination.pub) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open2); open2->signature.bytes[0] ^= 1; node1.block_processor.add (open2); // Insert open2 in to the queue before open1 @@ -4486,12 +4344,12 @@ TEST (ledger, unchecked_open) // Waits for the last blocks to pass through block_processor and unchecked.put queues ASSERT_TIMELY_EQ (10s, 1, node1.unchecked.count ()); // Get the next peer for attempting a tcp bootstrap connection - auto blocks = node1.unchecked.get (open1->source ()); + auto blocks = node1.unchecked.get (open1->source_field ().value ()); ASSERT_EQ (blocks.size (), 1); } node1.block_processor.add (send1); // Waits for the send1 block to pass through block_processor and unchecked.put queues - ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), open1->hash ())); + ASSERT_TIMELY (5s, node1.ledger.block_exists (node1.store.tx_begin_read (), open1->hash ())); ASSERT_EQ (0, node1.unchecked.count ()); } @@ -4503,25 +4361,25 @@ TEST (ledger, unchecked_receive) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 2 * nano::Gxrb_ratio) .link (destination.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); auto open1 = builder .open () @@ -4530,7 +4388,7 @@ TEST (ledger, unchecked_receive) .account (destination.pub) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open1); auto receive1 = builder .receive () @@ -4538,7 +4396,7 @@ TEST (ledger, unchecked_receive) .source (send2->hash ()) .sign (destination.prv, destination.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*receive1); node1.block_processor.add (send1); node1.block_processor.add (receive1); @@ -4554,15 +4412,15 @@ TEST (ledger, unchecked_receive) } // Waits for the open1 block to pass through block_processor and unchecked.put queues node1.block_processor.add (open1); - ASSERT_TIMELY (15s, check_block_is_listed (node1.store.tx_begin_read (), receive1->source ())); + ASSERT_TIMELY (15s, check_block_is_listed (node1.store.tx_begin_read (), receive1->source_field ().value ())); // Previous block for receive1 is known, signature was validated { auto transaction = node1.store.tx_begin_read (); - auto blocks (node1.unchecked.get (receive1->source ())); + auto blocks (node1.unchecked.get (receive1->source_field ().value ())); ASSERT_EQ (blocks.size (), 1); } node1.block_processor.add (send2); - ASSERT_TIMELY (10s, node1.store.block.exists (node1.store.tx_begin_read (), receive1->hash ())); + ASSERT_TIMELY (10s, node1.ledger.block_exists (node1.store.tx_begin_read (), receive1->hash ())); ASSERT_EQ (0, node1.unchecked.count ()); } @@ -4586,22 +4444,22 @@ TEST (ledger, confirmation_height_not_updated) .work (*pool.generate (account_info->head)) .build (); nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (1, confirmation_height_info.height); ASSERT_EQ (nano::dev::genesis->hash (), confirmation_height_info.frontier); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (1, confirmation_height_info.height); ASSERT_EQ (nano::dev::genesis->hash (), confirmation_height_info.frontier); auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key.pub) .sign (key.prv, key.pub) .work (*pool.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_TRUE (store.confirmation_height.get (transaction, key.pub, confirmation_height_info)); ASSERT_EQ (0, confirmation_height_info.height); ASSERT_EQ (nano::block_hash (0), confirmation_height_info.frontier); @@ -4622,7 +4480,7 @@ TEST (ledger, zero_rep) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (); auto transaction (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *block1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, block1)); ASSERT_EQ (0, node1.ledger.cache.rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount, node1.ledger.cache.rep_weights.representation_get (0)); auto block2 = builder.state () @@ -4634,7 +4492,7 @@ TEST (ledger, zero_rep) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (block1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *block2).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, block2)); ASSERT_EQ (nano::dev::constants.genesis_amount, node1.ledger.cache.rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (0, node1.ledger.cache.rep_weights.representation_get (0)); } @@ -4650,74 +4508,74 @@ TEST (ledger, work_validation) nano::keypair key; // With random work the block doesn't pass, then modifies the block with sufficient work and ensures a correct result - auto process_block = [&store, &ledger, &pool] (nano::block & block_a, nano::block_details const details_a) { - auto threshold = nano::dev::network_params.work.threshold (block_a.work_version (), details_a); + auto process_block = [&store, &ledger, &pool] (std::shared_ptr block_a, nano::block_details const details_a) { + auto threshold = nano::dev::network_params.work.threshold (block_a->work_version (), details_a); // Rarely failed with random work, so modify until it doesn't have enough difficulty - while (nano::dev::network_params.work.difficulty (block_a) >= threshold) + while (nano::dev::network_params.work.difficulty (*block_a) >= threshold) { - block_a.block_work_set (block_a.block_work () + 1); + block_a->block_work_set (block_a->block_work () + 1); } - EXPECT_EQ (nano::process_result::insufficient_work, ledger.process (store.tx_begin_write (), block_a).code); - block_a.block_work_set (*pool.generate (block_a.root (), threshold)); - EXPECT_EQ (nano::process_result::progress, ledger.process (store.tx_begin_write (), block_a).code); + EXPECT_EQ (nano::block_status::insufficient_work, ledger.process (store.tx_begin_write (), block_a)); + block_a->block_work_set (*pool.generate (block_a->root (), threshold)); + EXPECT_EQ (nano::block_status::progress, ledger.process (store.tx_begin_write (), block_a)); }; std::error_code ec; - auto send = *builder.send () - .previous (nano::dev::genesis->hash ()) - .destination (gen.pub) - .balance (nano::dev::constants.genesis_amount - 1) - .sign (gen.prv, gen.pub) - .work (0) - .build (ec); - ASSERT_FALSE (ec); - - auto receive = *builder.receive () - .previous (send.hash ()) - .source (send.hash ()) - .sign (gen.prv, gen.pub) - .work (0) - .build (ec); + auto send = builder.send () + .previous (nano::dev::genesis->hash ()) + .destination (gen.pub) + .balance (nano::dev::constants.genesis_amount - 1) + .sign (gen.prv, gen.pub) + .work (0) + .build (ec); ASSERT_FALSE (ec); - auto change = *builder.change () - .previous (receive.hash ()) - .representative (key.pub) + auto receive = builder.receive () + .previous (send->hash ()) + .source (send->hash ()) .sign (gen.prv, gen.pub) .work (0) .build (ec); ASSERT_FALSE (ec); - auto state = *builder.state () - .account (gen.pub) - .previous (change.hash ()) - .representative (gen.pub) - .balance (nano::dev::constants.genesis_amount - 1) - .link (key.pub) + auto change = builder.change () + .previous (receive->hash ()) + .representative (key.pub) .sign (gen.prv, gen.pub) .work (0) .build (ec); ASSERT_FALSE (ec); - auto open = *builder.open () - .account (key.pub) - .source (state.hash ()) - .representative (key.pub) - .sign (key.prv, key.pub) + auto state = builder.state () + .account (gen.pub) + .previous (change->hash ()) + .representative (gen.pub) + .balance (nano::dev::constants.genesis_amount - 1) + .link (key.pub) + .sign (gen.prv, gen.pub) .work (0) .build (ec); ASSERT_FALSE (ec); - auto epoch = *builder.state () - .account (key.pub) - .previous (open.hash ()) - .balance (1) - .representative (key.pub) - .link (ledger.epoch_link (nano::epoch::epoch_1)) - .sign (gen.prv, gen.pub) - .work (0) - .build (ec); + auto open = builder.open () + .account (key.pub) + .source (state->hash ()) + .representative (key.pub) + .sign (key.prv, key.pub) + .work (0) + .build (ec); + ASSERT_FALSE (ec); + + auto epoch = builder.state () + .account (key.pub) + .previous (open->hash ()) + .balance (1) + .representative (key.pub) + .link (ledger.epoch_link (nano::epoch::epoch_1)) + .sign (gen.prv, gen.pub) + .work (0) + .build (ec); ASSERT_FALSE (ec); process_block (send, {}); @@ -4739,67 +4597,67 @@ TEST (ledger, dependents_confirmed) nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; nano::keypair key1; auto send1 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_TRUE (ledger.dependents_confirmed (transaction, *send1)); auto send2 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 200) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_FALSE (ledger.dependents_confirmed (transaction, *send2)); auto receive1 = builder.state () .account (key1.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (100) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); ASSERT_FALSE (ledger.dependents_confirmed (transaction, *receive1)); nano::confirmation_height_info height; - ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis->account (), height)); + ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, height)); height.height += 1; - ledger.store.confirmation_height.put (transaction, nano::dev::genesis->account (), height); + ledger.store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, height); ASSERT_TRUE (ledger.dependents_confirmed (transaction, *receive1)); auto receive2 = builder.state () .account (key1.pub) .previous (receive1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (200) .link (send2->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (receive1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2)); ASSERT_FALSE (ledger.dependents_confirmed (transaction, *receive2)); ASSERT_TRUE (ledger.store.confirmation_height.get (transaction, key1.pub, height)); height.height += 1; ledger.store.confirmation_height.put (transaction, key1.pub, height); ASSERT_FALSE (ledger.dependents_confirmed (transaction, *receive2)); - ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis->account (), height)); + ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, height)); height.height += 1; - ledger.store.confirmation_height.put (transaction, nano::dev::genesis->account (), height); + ledger.store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, height); ASSERT_TRUE (ledger.dependents_confirmed (transaction, *receive2)); } TEST (ledger, dependents_confirmed_pruning) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::stats stats; @@ -4811,40 +4669,40 @@ TEST (ledger, dependents_confirmed_pruning) nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; nano::keypair key1; auto send1 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); auto send2 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 200) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); nano::confirmation_height_info height; - ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis->account (), height)); + ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, height)); height.height = 3; - ledger.store.confirmation_height.put (transaction, nano::dev::genesis->account (), height); + ledger.store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, height); ASSERT_TRUE (ledger.block_confirmed (transaction, send1->hash ())); ASSERT_EQ (2, ledger.pruning_action (transaction, send2->hash (), 1)); auto receive1 = builder.state () .account (key1.pub) .previous (0) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (100) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) - .build_shared (); + .build (); ASSERT_TRUE (ledger.dependents_confirmed (transaction, *receive1)); } @@ -4859,9 +4717,9 @@ TEST (ledger, block_confirmed) nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; nano::keypair key1; auto send1 = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -4869,12 +4727,12 @@ TEST (ledger, block_confirmed) .build (); // Must be safe against non-existing blocks ASSERT_FALSE (ledger.block_confirmed (transaction, send1->hash ())); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_FALSE (ledger.block_confirmed (transaction, send1->hash ())); nano::confirmation_height_info height; - ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis->account (), height)); + ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, height)); ++height.height; - ledger.store.confirmation_height.put (transaction, nano::dev::genesis->account (), height); + ledger.store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, height); ASSERT_TRUE (ledger.block_confirmed (transaction, send1->hash ())); } @@ -4902,16 +4760,16 @@ TEST (ledger, cache) ASSERT_EQ (account_count, cache_a.account_count); ASSERT_EQ (block_count, cache_a.block_count); ASSERT_EQ (cemented_count, cache_a.cemented_count); - ASSERT_EQ (genesis_weight, cache_a.rep_weights.representation_get (nano::dev::genesis->account ())); + ASSERT_EQ (genesis_weight, cache_a.rep_weights.representation_get (nano::dev::genesis_key.pub)); ASSERT_EQ (pruned_count, cache_a.pruned_count); }; nano::keypair key; - auto const latest = ledger.latest (store.tx_begin_read (), nano::dev::genesis->account ()); + auto const latest = ledger.latest (store.tx_begin_read (), nano::dev::genesis_key.pub); auto send = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - (i + 1)) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -4928,7 +4786,7 @@ TEST (ledger, cache) .build (); { auto transaction (store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); } ++block_count; @@ -4938,7 +4796,7 @@ TEST (ledger, cache) { auto transaction (store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); } ++block_count; @@ -4949,10 +4807,10 @@ TEST (ledger, cache) { auto transaction (store.tx_begin_write ()); nano::confirmation_height_info height; - ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis->account (), height)); + ASSERT_FALSE (ledger.store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, height)); ++height.height; height.frontier = send->hash (); - ledger.store.confirmation_height.put (transaction, nano::dev::genesis->account (), height); + ledger.store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, height); ASSERT_TRUE (ledger.block_confirmed (transaction, send->hash ())); ++ledger.cache.cemented_count; } @@ -4989,7 +4847,7 @@ TEST (ledger, cache) TEST (ledger, pruning_action) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5001,36 +4859,36 @@ TEST (ledger, pruning_action) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_TRUE (store->block.exists (transaction, send1->hash ())); auto send1_stored (store->block.get (transaction, send1->hash ())); ASSERT_NE (nullptr, send1_stored); ASSERT_EQ (*send1, *send1_stored); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); // Pruning action ASSERT_EQ (1, ledger.pruning_action (transaction, send1->hash (), 1)); ASSERT_EQ (0, ledger.pruning_action (transaction, nano::dev::genesis->hash (), 1)); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_FALSE (store->block.exists (transaction, send1->hash ())); ASSERT_TRUE (ledger.block_or_pruned_exists (transaction, send1->hash ())); // Pruned ledger start without proper flags emulation @@ -5043,23 +4901,23 @@ TEST (ledger, pruning_action) // Receiving pruned block auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); ASSERT_TRUE (store->block.exists (transaction, receive1->hash ())); auto receive1_stored (store->block.get (transaction, receive1->hash ())); ASSERT_NE (nullptr, receive1_stored); ASSERT_EQ (*receive1, *receive1_stored); - ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (4, receive1_stored->sideband ().height); - ASSERT_FALSE (receive1_stored->sideband ().details.is_send); - ASSERT_TRUE (receive1_stored->sideband ().details.is_receive); + ASSERT_FALSE (receive1_stored->is_send ()); + ASSERT_TRUE (receive1_stored->is_receive ()); ASSERT_FALSE (receive1_stored->sideband ().details.is_epoch); // Middle block pruning ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); @@ -5073,7 +4931,7 @@ TEST (ledger, pruning_action) TEST (ledger, pruning_large_chain) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5089,27 +4947,27 @@ TEST (ledger, pruning_large_chain) { auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (last_hash) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (last_hash)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); ASSERT_TRUE (store->block.exists (transaction, send->hash ())); auto receive = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (send->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); ASSERT_TRUE (store->block.exists (transaction, receive->hash ())); last_hash = receive->hash (); } @@ -5128,7 +4986,7 @@ TEST (ledger, pruning_large_chain) TEST (ledger, pruning_source_rollback) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5140,38 +4998,38 @@ TEST (ledger, pruning_source_rollback) nano::block_builder builder; auto epoch1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, epoch1)); auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (epoch1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (epoch1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); // Pruning action ASSERT_EQ (2, ledger.pruning_action (transaction, send1->hash (), 1)); @@ -5180,43 +5038,43 @@ TEST (ledger, pruning_source_rollback) ASSERT_FALSE (store->block.exists (transaction, epoch1->hash ())); ASSERT_TRUE (store->pruned.exists (transaction, epoch1->hash ())); ASSERT_TRUE (store->block.exists (transaction, nano::dev::genesis->hash ())); - auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + auto info = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info); - ASSERT_EQ (nano::dev::genesis->account (), info->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info->source); ASSERT_EQ (nano::Gxrb_ratio, info->amount.number ()); ASSERT_EQ (nano::epoch::epoch_1, info->epoch); // Receiving pruned block auto receive1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (5, ledger.cache.block_count); // Rollback receive block ASSERT_FALSE (ledger.rollback (transaction, receive1->hash ())); - auto info2 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + auto info2 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info2); - ASSERT_NE (nano::dev::genesis->account (), info2->source); // Tradeoff to not store pruned blocks accounts + ASSERT_NE (nano::dev::genesis_key.pub, info2->source); // Tradeoff to not store pruned blocks accounts ASSERT_EQ (nano::Gxrb_ratio, info2->amount.number ()); ASSERT_EQ (nano::epoch::epoch_1, info2->epoch); // Process receive block again - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (5, ledger.cache.block_count); } TEST (ledger, pruning_source_rollback_legacy) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5229,13 +5087,13 @@ TEST (ledger, pruning_source_rollback_legacy) auto send1 = builder .send () .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); nano::keypair key1; auto send2 = builder .send () @@ -5245,20 +5103,20 @@ TEST (ledger, pruning_source_rollback_legacy) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (key1.pub, send2->hash ()))); auto send3 = builder .send () .previous (send2->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 3 * nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send3)); ASSERT_TRUE (store->block.exists (transaction, send3->hash ())); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send3->hash ()))); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send3->hash ()))); // Pruning action ASSERT_EQ (2, ledger.pruning_action (transaction, send2->hash (), 1)); ASSERT_FALSE (store->block.exists (transaction, send2->hash ())); @@ -5266,14 +5124,14 @@ TEST (ledger, pruning_source_rollback_legacy) ASSERT_FALSE (store->block.exists (transaction, send1->hash ())); ASSERT_TRUE (store->pruned.exists (transaction, send1->hash ())); ASSERT_TRUE (store->block.exists (transaction, nano::dev::genesis->hash ())); - auto info1 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + auto info1 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info1); - ASSERT_EQ (nano::dev::genesis->account (), info1->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info1->source); ASSERT_EQ (nano::Gxrb_ratio, info1->amount.number ()); ASSERT_EQ (nano::epoch::epoch_0, info1->epoch); auto info2 = ledger.pending_info (transaction, nano::pending_key (key1.pub, send2->hash ())); ASSERT_TRUE (info2); - ASSERT_EQ (nano::dev::genesis->account (), info2->source); + ASSERT_EQ (nano::dev::genesis_key.pub, info2->source); ASSERT_EQ (nano::Gxrb_ratio, info2->amount.number ()); ASSERT_EQ (nano::epoch::epoch_0, info2->epoch); // Receiving pruned block @@ -5284,32 +5142,32 @@ TEST (ledger, pruning_source_rollback_legacy) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send3->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (5, ledger.cache.block_count); // Rollback receive block ASSERT_FALSE (ledger.rollback (transaction, receive1->hash ())); - auto info3 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ())); + auto info3 = ledger.pending_info (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ())); ASSERT_TRUE (info3); - ASSERT_NE (nano::dev::genesis->account (), info3->source); // Tradeoff to not store pruned blocks accounts + ASSERT_NE (nano::dev::genesis_key.pub, info3->source); // Tradeoff to not store pruned blocks accounts ASSERT_EQ (nano::Gxrb_ratio, info3->amount.number ()); ASSERT_EQ (nano::epoch::epoch_0, info3->epoch); // Process receive block again - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); - ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); + ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (5, ledger.cache.block_count); // Receiving pruned block (open) auto open1 = builder .open () .source (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (key1.pub, send2->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (6, ledger.cache.block_count); @@ -5317,11 +5175,11 @@ TEST (ledger, pruning_source_rollback_legacy) ASSERT_FALSE (ledger.rollback (transaction, open1->hash ())); auto info4 = ledger.pending_info (transaction, nano::pending_key (key1.pub, send2->hash ())); ASSERT_TRUE (info4); - ASSERT_NE (nano::dev::genesis->account (), info4->source); // Tradeoff to not store pruned blocks accounts + ASSERT_NE (nano::dev::genesis_key.pub, info4->source); // Tradeoff to not store pruned blocks accounts ASSERT_EQ (nano::Gxrb_ratio, info4->amount.number ()); ASSERT_EQ (nano::epoch::epoch_0, info4->epoch); // Process open block again - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); ASSERT_FALSE (store->pending.exists (transaction, nano::pending_key (key1.pub, send2->hash ()))); ASSERT_EQ (2, ledger.cache.pruned_count); ASSERT_EQ (6, ledger.cache.block_count); @@ -5329,7 +5187,7 @@ TEST (ledger, pruning_source_rollback_legacy) TEST (ledger, pruning_process_error) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5341,15 +5199,15 @@ TEST (ledger, pruning_process_error) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_EQ (0, ledger.cache.pruned_count); ASSERT_EQ (2, ledger.cache.block_count); // Pruning action for latest block (not valid action) @@ -5357,26 +5215,26 @@ TEST (ledger, pruning_process_error) ASSERT_FALSE (store->block.exists (transaction, send1->hash ())); ASSERT_TRUE (store->pruned.exists (transaction, send1->hash ())); // Attempt to process pruned block again - ASSERT_EQ (nano::process_result::old, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::old, ledger.process (transaction, send1)); // Attept to process new block after pruned auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::gap_previous, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::gap_previous, ledger.process (transaction, send2)); ASSERT_EQ (1, ledger.cache.pruned_count); ASSERT_EQ (2, ledger.cache.block_count); } TEST (ledger, pruning_legacy_blocks) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5390,13 +5248,13 @@ TEST (ledger, pruning_legacy_blocks) auto send1 = builder .send () .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); - ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis->account (), send1->hash ()))); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + ASSERT_TRUE (store->pending.exists (transaction, nano::pending_key (nano::dev::genesis_key.pub, send1->hash ()))); auto receive1 = builder .receive () .previous (send1->hash ()) @@ -5404,7 +5262,7 @@ TEST (ledger, pruning_legacy_blocks) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1)); auto change1 = builder .change () .previous (receive1->hash ()) @@ -5412,7 +5270,7 @@ TEST (ledger, pruning_legacy_blocks) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (receive1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *change1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change1)); auto send2 = builder .send () .previous (change1->hash ()) @@ -5421,25 +5279,25 @@ TEST (ledger, pruning_legacy_blocks) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (change1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); auto open1 = builder .open () .source (send2->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*pool.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open1)); auto send3 = builder .send () .previous (open1->hash ()) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (0) .sign (key1.prv, key1.pub) .work (*pool.generate (open1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send3).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send3)); // Pruning action ASSERT_EQ (3, ledger.pruning_action (transaction, change1->hash (), 2)); ASSERT_EQ (1, ledger.pruning_action (transaction, open1->hash (), 1)); @@ -5462,7 +5320,7 @@ TEST (ledger, pruning_legacy_blocks) TEST (ledger, pruning_safe_functions) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5474,27 +5332,27 @@ TEST (ledger, pruning_safe_functions) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_TRUE (store->block.exists (transaction, send1->hash ())); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); // Pruning action ASSERT_EQ (1, ledger.pruning_action (transaction, send1->hash (), 1)); @@ -5504,26 +5362,16 @@ TEST (ledger, pruning_safe_functions) ASSERT_TRUE (store->block.exists (transaction, nano::dev::genesis->hash ())); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); // Safe ledger actions - bool error (false); - ASSERT_EQ (0, ledger.balance_safe (transaction, send1->hash (), error)); - ASSERT_TRUE (error); - error = false; - ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, ledger.balance_safe (transaction, send2->hash (), error)); - ASSERT_FALSE (error); - error = false; - ASSERT_EQ (0, ledger.amount_safe (transaction, send2->hash (), error)); - ASSERT_TRUE (error); - error = false; - ASSERT_TRUE (ledger.account_safe (transaction, send1->hash (), error).is_zero ()); - ASSERT_TRUE (error); - error = false; - ASSERT_EQ (nano::dev::genesis->account (), ledger.account_safe (transaction, send2->hash (), error)); - ASSERT_FALSE (error); + ASSERT_FALSE (ledger.balance (transaction, send1->hash ())); + ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, ledger.balance (transaction, send2->hash ()).value ()); + ASSERT_FALSE (ledger.amount (transaction, send2->hash ())); + ASSERT_FALSE (ledger.account (transaction, send1->hash ())); + ASSERT_EQ (nano::dev::genesis_key.pub, ledger.account (transaction, send2->hash ()).value ()); } TEST (ledger, hash_root_random) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::stats stats; @@ -5535,27 +5383,27 @@ TEST (ledger, hash_root_random) nano::block_builder builder; auto send1 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_TRUE (store->block.exists (transaction, send1->hash ())); auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); ASSERT_TRUE (store->block.exists (transaction, send2->hash ())); // Pruning action ASSERT_EQ (1, ledger.pruning_action (transaction, send1->hash (), 1)); @@ -5587,7 +5435,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb) { nano::test::system system{}; auto path = nano::unique_path (); - nano::logger_mt logger{}; + nano::logger logger; boost::asio::ip::address_v6 address (boost::asio::ip::make_address_v6 ("::ffff:127.0.0.1")); uint16_t port = 100; nano::store::lmdb::component store{ logger, path / "data.ldb", nano::dev::constants }; @@ -5602,7 +5450,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::endpoint_key endpoint_key (address.to_bytes (), port); auto version = nano::store::component::version_current; @@ -5613,13 +5461,13 @@ TEST (ledger, migrate_lmdb_to_rocksdb) ASSERT_FALSE (store.init_error ()); // Lower the database to the max version unsupported for upgrades - store.confirmation_height.put (transaction, nano::dev::genesis->account (), { 2, send->hash () }); + store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, { 2, send->hash () }); store.online_weight.put (transaction, 100, nano::amount (2)); store.frontier.put (transaction, nano::block_hash (2), nano::account (5)); store.peer.put (transaction, endpoint_key); - store.pending.put (transaction, nano::pending_key (nano::dev::genesis->account (), send->hash ()), nano::pending_info (nano::dev::genesis->account (), 100, nano::epoch::epoch_0)); + store.pending.put (transaction, nano::pending_key (nano::dev::genesis_key.pub, send->hash ()), nano::pending_info (nano::dev::genesis_key.pub, 100, nano::epoch::epoch_0)); store.pruned.put (transaction, send->hash ()); store.version.put (transaction, version); send->sideband_set ({}); @@ -5633,8 +5481,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb) nano::store::rocksdb::component rocksdb_store{ logger, path / "rocksdb", nano::dev::constants }; auto rocksdb_transaction (rocksdb_store.tx_begin_read ()); - nano::pending_info pending_info{}; - ASSERT_FALSE (rocksdb_store.pending.get (rocksdb_transaction, nano::pending_key (nano::dev::genesis->account (), send->hash ()), pending_info)); + ASSERT_TRUE (rocksdb_store.pending.get (rocksdb_transaction, nano::pending_key (nano::dev::genesis_key.pub, send->hash ()))); for (auto i = rocksdb_store.online_weight.begin (rocksdb_transaction); i != rocksdb_store.online_weight.end (); ++i) { @@ -5651,7 +5498,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb) ASSERT_EQ (rocksdb_store.version.get (rocksdb_transaction), version); ASSERT_EQ (rocksdb_store.frontier.get (rocksdb_transaction, 2), 5); nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (rocksdb_store.confirmation_height.get (rocksdb_transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE (rocksdb_store.confirmation_height.get (rocksdb_transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (confirmation_height_info.height, 2); ASSERT_EQ (confirmation_height_info.frontier, send->hash ()); ASSERT_EQ (rocksdb_store.final_vote.get (rocksdb_transaction, nano::root (send->previous ())).size (), 1); @@ -5670,23 +5517,23 @@ TEST (ledger, unconfirmed_frontiers) nano::state_block_builder builder; nano::keypair key; - auto const latest = ledger.latest (store.tx_begin_read (), nano::dev::genesis->account ()); + auto const latest = ledger.latest (store.tx_begin_read (), nano::dev::genesis_key.pub); auto send = builder.make_block () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - 100) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (store.tx_begin_write (), *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (store.tx_begin_write (), send)); unconfirmed_frontiers = ledger.unconfirmed_frontiers (); ASSERT_EQ (unconfirmed_frontiers.size (), 1); ASSERT_EQ (unconfirmed_frontiers.begin ()->first, 1); - nano::uncemented_info uncemented_info1{ latest, send->hash (), nano::dev::genesis->account () }; + nano::uncemented_info uncemented_info1{ latest, send->hash (), nano::dev::genesis_key.pub }; auto uncemented_info2 = unconfirmed_frontiers.begin ()->second; ASSERT_EQ (uncemented_info1.account, uncemented_info2.account); ASSERT_EQ (uncemented_info1.cemented_frontier, uncemented_info2.cemented_frontier); @@ -5699,7 +5546,7 @@ TEST (ledger, is_send_genesis) auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); - ASSERT_FALSE (ledger.is_send (tx, *nano::dev::genesis)); + ASSERT_FALSE (nano::dev::genesis->is_send ()); } TEST (ledger, is_send_state) @@ -5708,8 +5555,8 @@ TEST (ledger, is_send_state) auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); - ASSERT_TRUE (ledger.is_send (tx, *ctx.blocks ()[0])); - ASSERT_FALSE (ledger.is_send (tx, *ctx.blocks ()[1])); + ASSERT_TRUE (ctx.blocks ()[0]->is_send ()); + ASSERT_FALSE (ctx.blocks ()[1]->is_send ()); } TEST (ledger, is_send_legacy) @@ -5718,8 +5565,8 @@ TEST (ledger, is_send_legacy) auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); - ASSERT_TRUE (ledger.is_send (tx, *ctx.blocks ()[0])); - ASSERT_FALSE (ledger.is_send (tx, *ctx.blocks ()[1])); + ASSERT_TRUE (ctx.blocks ()[0]->is_send ()); + ASSERT_FALSE (ctx.blocks ()[1]->is_send ()); } TEST (ledger, head_block) @@ -5728,5 +5575,5 @@ TEST (ledger, head_block) auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); - ASSERT_EQ (*nano::dev::genesis, *ledger.head_block (tx, nano::dev::genesis->account ())); + ASSERT_EQ (*nano::dev::genesis, *ledger.head_block (tx, nano::dev::genesis_key.pub)); } diff --git a/nano/core_test/logger.cpp b/nano/core_test/logger.cpp deleted file mode 100644 index 4a318b9cca..0000000000 --- a/nano/core_test/logger.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include -#include - -#include - -#include -#include -#include - -using namespace std::chrono_literals; - -TEST (logger, changing_time_interval) -{ - auto path1 (nano::unique_path ()); - nano::logging logging; - logging.init (path1); - logging.min_time_between_log_output = 0ms; - nano::logger_mt my_logger (logging.min_time_between_log_output); - auto error (my_logger.try_log ("logger.changing_time_interval1")); - ASSERT_FALSE (error); - my_logger.min_log_delta = 20s; - error = my_logger.try_log ("logger, changing_time_interval2"); - ASSERT_TRUE (error); -} - -TEST (logger, try_log) -{ - auto path1 (nano::unique_path ()); - std::stringstream ss; - nano::test::boost_log_cerr_redirect redirect_cerr (ss.rdbuf ()); - nano::logger_mt my_logger (100ms); - auto output1 = "logger.try_log1"; - auto error (my_logger.try_log (output1)); - ASSERT_FALSE (error); - auto output2 = "logger.try_log2"; - error = my_logger.try_log (output2); - ASSERT_TRUE (error); // Fails as it is occuring too soon - - // Sleep for a bit and then confirm - std::this_thread::sleep_for (100ms); - error = my_logger.try_log (output2); - ASSERT_FALSE (error); - - std::string str; - std::getline (ss, str, '\n'); - ASSERT_STREQ (str.c_str (), output1); - std::getline (ss, str, '\n'); - ASSERT_STREQ (str.c_str (), output2); -} - -TEST (logger, always_log) -{ - auto path1 (nano::unique_path ()); - std::stringstream ss; - nano::test::boost_log_cerr_redirect redirect_cerr (ss.rdbuf ()); - nano::logger_mt my_logger (20s); // Make time interval effectively unreachable - auto output1 = "logger.always_log1"; - auto error (my_logger.try_log (output1)); - ASSERT_FALSE (error); - - // Time is too soon after, so it won't be logged - auto output2 = "logger.always_log2"; - error = my_logger.try_log (output2); - ASSERT_TRUE (error); - - // Force it to be logged - my_logger.always_log (output2); - - std::string str; - std::getline (ss, str, '\n'); - ASSERT_STREQ (str.c_str (), output1); - std::getline (ss, str, '\n'); - ASSERT_STREQ (str.c_str (), output2); -} - -TEST (logger, stable_filename) -{ - auto path (nano::unique_path ()); - nano::logging logging; - - // Releasing allows setting up logging again - logging.release_file_sink (); - - logging.stable_log_filename = true; - logging.init (path); - - nano::logger_mt logger (logging.min_time_between_log_output); - logger.always_log ("stable1"); - - auto log_file = path / "log" / "node.log"; - -#if BOOST_VERSION >= 107000 - EXPECT_TRUE (std::filesystem::exists (log_file)); - // Try opening it again - logging.release_file_sink (); - logging.init (path); - logger.always_log ("stable2"); -#else - // When using Boost < 1.70 , behavior is reverted to not using the stable filename - EXPECT_FALSE (std::filesystem::exists (log_file)); -#endif - - // Reset the logger - logging.release_file_sink (); - nano::logging ().init (path); -} diff --git a/nano/core_test/logging.cpp b/nano/core_test/logging.cpp new file mode 100644 index 0000000000..0ee857d158 --- /dev/null +++ b/nano/core_test/logging.cpp @@ -0,0 +1,106 @@ +#include +#include + +#include + +#include + +using namespace std::chrono_literals; + +namespace +{ +struct non_copyable +{ + non_copyable () = default; + non_copyable (non_copyable const &) = delete; + non_copyable (non_copyable &&) = default; + non_copyable & operator= (non_copyable const &) = delete; + non_copyable & operator= (non_copyable &&) = default; + + friend std::ostream & operator<< (std::ostream & os, non_copyable const & nc) + { + os << "non_copyable"; + return os; + } +}; +} + +TEST (tracing, no_copy) +{ + non_copyable nc; + + nano::logger logger; + logger.trace (nano::log::type::test, nano::log::detail::test, nano::log::arg{ "non_copyable", nc }); +} + +namespace +{ +struct non_moveable +{ + non_moveable () = default; + non_moveable (non_moveable const &) = delete; + non_moveable (non_moveable &&) = delete; + non_moveable & operator= (non_moveable const &) = delete; + non_moveable & operator= (non_moveable &&) = delete; + + friend std::ostream & operator<< (std::ostream & os, non_moveable const & nm) + { + os << "non_moveable"; + return os; + } +}; +} + +TEST (tracing, no_move) +{ + non_moveable nm; + + nano::logger logger; + logger.trace (nano::log::type::test, nano::log::detail::test, nano::log::arg{ "non_moveable", nm }); +} + +TEST (log_parse, parse_level) +{ + ASSERT_EQ (nano::log::parse_level ("error"), nano::log::level::error); + ASSERT_EQ (nano::log::parse_level ("off"), nano::log::level::off); + ASSERT_THROW (nano::log::parse_level ("enumnotpresent"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_level (""), std::invalid_argument); + ASSERT_THROW (nano::log::parse_level ("_last"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_level ("_error"), std::invalid_argument); +} + +TEST (log_parse, parse_type) +{ + ASSERT_EQ (nano::log::parse_type ("node"), nano::log::type::node); + ASSERT_THROW (nano::log::parse_type ("enumnotpresent"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_type (""), std::invalid_argument); + ASSERT_THROW (nano::log::parse_type ("_last"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_type ("_node"), std::invalid_argument); +} + +TEST (log_parse, parse_detail) +{ + ASSERT_EQ (nano::log::parse_detail ("all"), nano::log::detail::all); + ASSERT_EQ (nano::log::parse_detail ("process_confirmed"), nano::log::detail::process_confirmed); + ASSERT_THROW (nano::log::parse_detail ("enumnotpresent"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_detail (""), std::invalid_argument); + ASSERT_THROW (nano::log::parse_detail ("_last"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_detail ("_all"), std::invalid_argument); +} + +TEST (log_parse, parse_logger_id) +{ + ASSERT_EQ (nano::log::parse_logger_id ("node"), std::make_pair (nano::log::type::node, nano::log::detail::all)); + ASSERT_EQ (nano::log::parse_logger_id ("node::all"), std::make_pair (nano::log::type::node, nano::log::detail::all)); + ASSERT_EQ (nano::log::parse_logger_id ("node::process_confirmed"), std::make_pair (nano::log::type::node, nano::log::detail::process_confirmed)); + ASSERT_THROW (nano::log::parse_logger_id ("_last"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("node::enumnotpresent"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("node::"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("node::_all"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("enumnotpresent"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("invalid."), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("invalid._all"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("::"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id ("::all"), std::invalid_argument); + ASSERT_THROW (nano::log::parse_logger_id (""), std::invalid_argument); +} \ No newline at end of file diff --git a/nano/core_test/memory_pool.cpp b/nano/core_test/memory_pool.cpp index 3e5049bc0c..1d9c1fc1b8 100644 --- a/nano/core_test/memory_pool.cpp +++ b/nano/core_test/memory_pool.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/core_test/message.cpp b/nano/core_test/message.cpp index 29e70e371c..3053bbf04c 100644 --- a/nano/core_test/message.cpp +++ b/nano/core_test/message.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,7 +21,7 @@ std::shared_ptr random_block () .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); return block; } } @@ -165,7 +166,7 @@ TEST (message, confirm_ack_hash_serialization) hashes.push_back (block->hash ()); } nano::keypair representative1; - auto vote (std::make_shared (representative1.pub, representative1.prv, 0, 0, hashes)); + auto vote = nano::test::make_vote (representative1, { hashes }, 0, 0); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; std::vector bytes; { @@ -206,7 +207,7 @@ TEST (message, confirm_ack_hash_serialization_v2) } nano::keypair representative1; - auto vote (std::make_shared (representative1.pub, representative1.prv, 0, 0, hashes)); + auto vote = nano::test::make_vote (representative1, { hashes }, 0, 0); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; std::vector bytes; { @@ -362,22 +363,6 @@ TEST (message, confirm_req_hash_batch_serialization_v2) ASSERT_TRUE (header.confirm_is_v2 ()); } -// this unit test checks that conversion of message_header to string works as expected -TEST (message, message_header_to_string) -{ - // calculate expected string - int maxver = nano::dev::network_params.network.protocol_version; - int minver = nano::dev::network_params.network.protocol_version_min; - std::stringstream ss; - ss << "NetID: 5241(dev), VerMaxUsingMin: " << maxver << "/" << maxver << "/" << minver << ", MsgType: 2(keepalive), Extensions: 0000"; - auto expected_str = ss.str (); - - // check expected vs real - nano::keepalive keepalive_msg{ nano::dev::network_params.network }; - std::string header_string = keepalive_msg.header.to_string (); - ASSERT_EQ (expected_str, header_string); -} - /** * Test that a confirm_ack can encode an empty hash set */ @@ -834,4 +819,4 @@ TEST (handshake, signature_v2) message.v2->salt = nano::random_pool::generate (); ASSERT_FALSE (message.validate (cookie)); } -} \ No newline at end of file +} diff --git a/nano/core_test/message_deserializer.cpp b/nano/core_test/message_deserializer.cpp index e78d0fed23..44e9fa06df 100644 --- a/nano/core_test/message_deserializer.cpp +++ b/nano/core_test/message_deserializer.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -51,7 +52,7 @@ auto message_deserializer_success_checker (message_type & message_original) -> v ASSERT_EQ (*deserialized_bytes, *original_bytes); }); // This is a sanity test, to ensure the successful deserialization case passes. - ASSERT_EQ (message_deserializer->status, nano::transport::message_deserializer::parse_status::success); + ASSERT_EQ (message_deserializer->status, nano::transport::parse_status::success); } TEST (message_deserializer, exact_confirm_ack) @@ -65,7 +66,7 @@ TEST (message_deserializer, exact_confirm_ack) .balance (2) .sign (nano::keypair ().prv, 4) .work (*system.work.generate (nano::root (1))) - .build_shared (); + .build (); auto vote (std::make_shared (0, nano::keypair ().prv, 0, 0, std::vector{ block->hash () })); nano::confirm_ack message{ nano::dev::network_params.network, vote }; @@ -101,7 +102,7 @@ TEST (message_deserializer, exact_publish) .balance (2) .sign (nano::keypair ().prv, 4) .work (*system.work.generate (nano::root (1))) - .build_shared (); + .build (); nano::publish message{ nano::dev::network_params.network, block }; message_deserializer_success_checker (message); diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index 6804e7bb50..bf9ed2e651 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -1,9 +1,11 @@ +#include #include #include #include #include #include #include +#include #include #include #include @@ -57,8 +59,9 @@ TEST (network, tcp_connection) TEST (network, construction_with_specified_port) { nano::test::system system{}; - auto const port = system.get_available_port (/* do not allow 0 port */ false); - auto const node = system.add_node (nano::node_config{ port, system.logging }); + auto const port = nano::test::speculatively_choose_a_free_tcp_bind_port (); + ASSERT_NE (port, 0); + auto const node = system.add_node (nano::node_config{ port }); EXPECT_EQ (port, node->network.port); EXPECT_EQ (port, node->network.endpoint ().port ()); EXPECT_EQ (port, node->tcp_listener->endpoint ().port ()); @@ -79,7 +82,7 @@ TEST (network, send_node_id_handshake_tcp) nano::test::system system (1); auto node0 (system.nodes[0]); ASSERT_EQ (0, node0->network.size ()); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); node1->start (); system.nodes.push_back (node1); auto initial (node0->stats.count (nano::stat::type::message, nano::stat::detail::node_id_handshake, nano::stat::dir::in)); @@ -157,7 +160,7 @@ TEST (network, multi_keepalive) nano::test::system system (1); auto node0 = system.nodes[0]; ASSERT_EQ (0, node0->network.size ()); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); ASSERT_FALSE (node1->init_error ()); node1->start (); system.nodes.push_back (node1); @@ -165,7 +168,7 @@ TEST (network, multi_keepalive) ASSERT_EQ (0, node0->network.size ()); node1->network.tcp_channels.start_tcp (node0->network.endpoint ()); ASSERT_TIMELY (10s, node0->network.size () == 1 && node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive) >= 1); - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); ASSERT_FALSE (node2->init_error ()); node2->start (); system.nodes.push_back (node2); @@ -186,7 +189,7 @@ TEST (network, send_discarded_publish) .balance (2) .sign (nano::keypair ().prv, 4) .work (*system.work.generate (nano::root (1))) - .build_shared (); + .build (); { auto transaction (node1.store.tx_begin_read ()); node1.network.flood_block (block); @@ -212,7 +215,7 @@ TEST (network, send_invalid_publish) .balance (20) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::root (1))) - .build_shared (); + .build (); { auto transaction (node1.store.tx_begin_read ()); node1.network.flood_block (block); @@ -298,7 +301,7 @@ TEST (network, send_insufficient_work) .balance (20) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); nano::publish publish1{ nano::dev::network_params.network, block1 }; auto tcp_channel (node1.network.tcp_channels.find_node_id (node2.get_node_id ())); ASSERT_NE (nullptr, tcp_channel); @@ -314,7 +317,7 @@ TEST (network, send_insufficient_work) .balance (20) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (system.work_generate_limited (block1->hash (), node1.network_params.work.epoch_2_receive, node1.network_params.work.epoch_1 - 1)) - .build_shared (); + .build (); nano::publish publish2{ nano::dev::network_params.network, block2 }; tcp_channel->send (publish2, [] (boost::system::error_code const & ec, size_t size) {}); ASSERT_TIMELY (10s, node2.stats.count (nano::stat::type::error, nano::stat::detail::insufficient_work) != 1); @@ -327,7 +330,7 @@ TEST (network, send_insufficient_work) .balance (20) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (block2->hash (), node1.network_params.work.epoch_2)) - .build_shared (); + .build (); nano::publish publish3{ nano::dev::network_params.network, block3 }; tcp_channel->send (publish3, [] (boost::system::error_code const & ec, size_t size) {}); ASSERT_EQ (0, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in)); @@ -343,7 +346,7 @@ TEST (network, send_insufficient_work) .link (1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (system.work_generate_limited (block1->hash (), node1.network_params.work.epoch_2_receive, node1.network_params.work.epoch_1 - 1)) - .build_shared (); + .build (); nano::publish publish4{ nano::dev::network_params.network, block4 }; tcp_channel->send (publish4, [] (boost::system::error_code const & ec, size_t size) {}); ASSERT_TIMELY (10s, node2.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in) != 0); @@ -363,12 +366,12 @@ TEST (receivable_processor, confirm_insufficient_pos) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*block1); - ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (block1)); node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); nano::keypair key1; - auto vote (std::make_shared (key1.pub, key1.prv, 0, 0, std::vector{ block1->hash () })); + auto vote = nano::test::make_vote (key1, { block1 }, 0, 0); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; auto channel1 = std::make_shared (node1, node1); node1.network.inbound (con1, channel1); @@ -386,11 +389,11 @@ TEST (receivable_processor, confirm_sufficient_pos) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*block1); - ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (block1)); node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ block1->hash () })); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { block1 }, 0, 0); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; auto channel1 = std::make_shared (node1, node1); node1.network.inbound (con1, channel1); @@ -416,15 +419,15 @@ TEST (receivable_processor, send_with_receive) .balance (amount - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest1)) - .build_shared (); + .build (); ASSERT_EQ (amount, node1.balance (nano::dev::genesis_key.pub)); ASSERT_EQ (0, node1.balance (key2.pub)); ASSERT_EQ (amount, node2.balance (nano::dev::genesis_key.pub)); ASSERT_EQ (0, node2.balance (key2.pub)); node1.process_active (block1); - node1.block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (node1, { block1 })); node2.process_active (block1); - node2.block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (node2, { block1 })); ASSERT_EQ (amount - node1.config.receive_minimum.number (), node1.balance (nano::dev::genesis_key.pub)); ASSERT_EQ (0, node1.balance (key2.pub)); ASSERT_EQ (amount - node1.config.receive_minimum.number (), node2.balance (nano::dev::genesis_key.pub)); @@ -749,7 +752,7 @@ TEST (network, peer_max_tcp_attempts) auto node = system.add_node (node_flags); for (auto i (0); i < node->network_params.network.max_peers_per_ip; ++i) { - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); + auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags)); node2->start (); system.nodes.push_back (node2); // Start TCP attempt @@ -795,16 +798,16 @@ TEST (network, duplicate_detection) auto & node1 = *system.add_node (node_flags); nano::publish publish{ nano::dev::network_params.network, nano::dev::genesis }; - ASSERT_EQ (0, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish)); + ASSERT_EQ (0, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish_message)); // Publish duplicate detection through TCP auto tcp_channel = node0.network.tcp_channels.find_node_id (node1.get_node_id ()); ASSERT_NE (nullptr, tcp_channel); - ASSERT_EQ (0, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish)); + ASSERT_EQ (0, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish_message)); tcp_channel->send (publish); - ASSERT_TIMELY_EQ (2s, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish), 0); + ASSERT_TIMELY_EQ (2s, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish_message), 0); tcp_channel->send (publish); - ASSERT_TIMELY_EQ (2s, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish), 1); + ASSERT_TIMELY_EQ (2s, node1.stats.count (nano::stat::type::filter, nano::stat::detail::duplicate_publish_message), 1); } TEST (network, duplicate_revert_publish) @@ -826,7 +829,7 @@ TEST (network, duplicate_revert_publish) nano::uint128_t digest; ASSERT_FALSE (node.network.publish_filter.apply (bytes.data (), bytes.size (), &digest)); ASSERT_TRUE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); - auto other_node (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto other_node (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); other_node->start (); system.nodes.push_back (other_node); auto channel = nano::test::establish_tcp (system, *other_node, node.network.endpoint ()); @@ -957,7 +960,7 @@ TEST (network, tcp_no_connect_excluded_peers) nano::test::system system (1); auto node0 (system.nodes[0]); ASSERT_EQ (0, node0->network.size ()); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); node1->start (); system.nodes.push_back (node1); auto endpoint1_tcp (nano::transport::map_endpoint_to_tcp (node1->network.endpoint ())); @@ -1058,7 +1061,7 @@ TEST (network, cleanup_purge) nano::test::system system (1); auto & node1 (*system.nodes[0]); - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); node2->start (); system.nodes.push_back (node2); diff --git a/nano/core_test/network_filter.cpp b/nano/core_test/network_filter.cpp index 21f6f7ec58..a886ae9564 100644 --- a/nano/core_test/network_filter.cpp +++ b/nano/core_test/network_filter.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -45,7 +46,7 @@ TEST (network_filter, unit) .link (nano::public_key ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); one_block (new_block, false); for (int i = 0; i < 10; ++i) @@ -74,7 +75,7 @@ TEST (network_filter, many) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); nano::publish message{ nano::dev::network_params.network, block }; auto bytes (message.to_bytes ()); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 239d29d300..cf81a51bdb 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include @@ -6,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +28,7 @@ TEST (node, null_account) nano::account default_account{}; ASSERT_FALSE (default_account == nullptr); - ASSERT_TRUE (default_account != nullptr); + ASSERT_NE (default_account, nullptr); } TEST (node, stop) @@ -46,19 +49,19 @@ TEST (node, work_generate) { auto difficulty = nano::difficulty::from_multiplier (1.5, node.network_params.work.base); auto work = node.work_generate_blocking (version, root, difficulty); - ASSERT_TRUE (work.is_initialized ()); - ASSERT_TRUE (nano::dev::network_params.work.difficulty (version, root, *work) >= difficulty); + ASSERT_TRUE (work.has_value ()); + ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, work.value ()), difficulty); } { auto difficulty = nano::difficulty::from_multiplier (0.5, node.network_params.work.base); - boost::optional work; + std::optional work; do { work = node.work_generate_blocking (version, root, difficulty); - } while (nano::dev::network_params.work.difficulty (version, root, *work) >= node.network_params.work.base); - ASSERT_TRUE (work.is_initialized ()); - ASSERT_TRUE (nano::dev::network_params.work.difficulty (version, root, *work) >= difficulty); - ASSERT_FALSE (nano::dev::network_params.work.difficulty (version, root, *work) >= node.network_params.work.base); + } while (nano::dev::network_params.work.difficulty (version, root, work.value ()) >= node.network_params.work.base); + ASSERT_TRUE (work.has_value ()); + ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, work.value ()), difficulty); + ASSERT_FALSE (nano::dev::network_params.work.difficulty (version, root, work.value ()) >= node.network_params.work.base); } } @@ -67,10 +70,8 @@ TEST (node, block_store_path_failure) nano::test::system system; auto service (std::make_shared ()); auto path (nano::unique_path ()); - nano::logging logging; - logging.init (path); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto node (std::make_shared (*service, system.get_available_port (), path, logging, pool)); + auto node (std::make_shared (*service, system.get_available_port (), path, pool)); ASSERT_TRUE (node->wallets.items.empty ()); node->stop (); } @@ -100,7 +101,6 @@ TEST (node, password_fanout) auto path (nano::unique_path ()); nano::node_config config; config.peering_port = system.get_available_port (); - config.logging.init (path); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; config.password_fanout = 10; nano::node node (io_ctx, path, config, pool); @@ -117,18 +117,6 @@ TEST (node, balance) ASSERT_EQ (std::numeric_limits::max (), system.nodes[0]->ledger.account_balance (transaction, nano::dev::genesis_key.pub)); } -TEST (node, representative) -{ - nano::test::system system (1); - auto block1 (system.nodes[0]->rep_block (nano::dev::genesis_key.pub)); - { - auto transaction (system.nodes[0]->store.tx_begin_read ()); - ASSERT_TRUE (system.nodes[0]->ledger.store.block.exists (transaction, block1)); - } - nano::keypair key; - ASSERT_TRUE (system.nodes[0]->rep_block (key.pub).is_zero ()); -} - TEST (node, send_unkeyed) { nano::test::system system (1); @@ -185,21 +173,21 @@ TEST (node, send_out_of_order) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (send1->hash ()) .destination (key2.pub) .balance (std::numeric_limits::max () - 2 * node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); auto send3 = builder.make_block () .previous (send2->hash ()) .destination (key2.pub) .balance (std::numeric_limits::max () - 3 * node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send2->hash ())) - .build_shared (); + .build (); node1.process_active (send3); node1.process_active (send2); node1.process_active (send1); @@ -221,7 +209,7 @@ TEST (node, quick_confirm) .balance (node1.online_reps.delta () + 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1.process_active (send); ASSERT_TIMELY (10s, !node1.balance (key.pub).is_zero ()); ASSERT_EQ (node1.balance (nano::dev::genesis_key.pub), node1.online_reps.delta () + 1); @@ -241,7 +229,7 @@ TEST (node, node_receive_quorum) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1.process_active (send); ASSERT_TIMELY (10s, node1.ledger.block_or_pruned_exists (send->hash ())); ASSERT_TIMELY (10s, node1.active.election (nano::qualified_root (previous, previous)) != nullptr); @@ -266,7 +254,7 @@ TEST (node, node_receive_quorum) TEST (node, auto_bootstrap) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; @@ -278,7 +266,7 @@ TEST (node, auto_bootstrap) auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node0->config.receive_minimum.number ())); ASSERT_NE (nullptr, send1); ASSERT_TIMELY_EQ (10s, node0->balance (key2.pub), node0->config.receive_minimum.number ()); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags)); ASSERT_FALSE (node1->init_error ()); node1->start (); system.nodes.push_back (node1); @@ -298,7 +286,7 @@ TEST (node, auto_bootstrap) TEST (node, auto_bootstrap_reverse) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; @@ -307,7 +295,7 @@ TEST (node, auto_bootstrap_reverse) nano::keypair key2; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); system.wallet (0)->insert_adhoc (key2.prv); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags)); ASSERT_FALSE (node1->init_error ()); ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node0->config.receive_minimum.number ())); node1->start (); @@ -319,14 +307,14 @@ TEST (node, auto_bootstrap_reverse) TEST (node, auto_bootstrap_age) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; node_flags.bootstrap_interval = 1; auto node0 = system.add_node (config, node_flags); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work, node_flags)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags)); ASSERT_FALSE (node1->init_error ()); node1->start (); system.nodes.push_back (node1); @@ -340,27 +328,6 @@ TEST (node, auto_bootstrap_age) node1->stop (); } -// Test ensures the block processor adds the published block to the gap cache. -TEST (node, receive_gap) -{ - nano::test::system system (1); - auto & node1 (*system.nodes[0]); - ASSERT_EQ (0, node1.gap_cache.size ()); - auto block = nano::send_block_builder () - .previous (5) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (0) - .build_shared (); - node1.work_generate_blocking (*block); - nano::publish message{ nano::dev::network_params.network, block }; - auto channel1 = std::make_shared (node1); - node1.network.inbound (message, channel1); - node1.block_processor.flush (); - ASSERT_EQ (1, node1.gap_cache.size ()); -} - TEST (node, merge_peers) { nano::test::system system (1); @@ -416,46 +383,41 @@ TEST (node, search_receivable_multiple) TEST (node, search_receivable_confirmed) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node = system.add_node (node_config); nano::keypair key2; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + auto send1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node->config.receive_minimum.number ())); ASSERT_NE (nullptr, send1); + ASSERT_TIMELY (5s, nano::test::confirmed (*node, { send1 })); + auto send2 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node->config.receive_minimum.number ())); ASSERT_NE (nullptr, send2); - ASSERT_TIMELY (10s, node->active.empty ()); - bool confirmed (false); - system.deadline_set (5s); - while (!confirmed) - { - auto transaction (node->store.tx_begin_read ()); - confirmed = node->ledger.block_confirmed (transaction, send2->hash ()); - ASSERT_NO_ERROR (system.poll ()); - } + ASSERT_TIMELY (5s, nano::test::confirmed (*node, { send2 })); + { auto transaction (node->wallets.tx_begin_write ()); system.wallet (0)->store.erase (transaction, nano::dev::genesis_key.pub); } + system.wallet (0)->insert_adhoc (key2.prv); ASSERT_FALSE (system.wallet (0)->search_receivable (system.wallet (0)->wallets.tx_begin_read ())); - { - ASSERT_FALSE (node->active.active (send1->hash ())); - ASSERT_FALSE (node->active.active (send2->hash ())); - } - ASSERT_TIMELY_EQ (10s, node->balance (key2.pub), 2 * node->config.receive_minimum.number ()); + ASSERT_TIMELY (5s, !node->active.active (send1->hash ())); + ASSERT_TIMELY (5s, !node->active.active (send2->hash ())); + ASSERT_TIMELY_EQ (5s, node->balance (key2.pub), 2 * node->config.receive_minimum.number ()); } TEST (node, search_receivable_pruned) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node1 = system.add_node (node_config); nano::node_flags node_flags; node_flags.enable_pruning = true; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.enable_voting = false; // Remove after allowing pruned voting auto node2 = system.add_node (config, node_flags); nano::keypair key2; @@ -542,21 +504,19 @@ TEST (node, confirm_locked) .balance (0) .sign (nano::keypair ().prv, 0) .work (0) - .build_shared (); + .build (); system.nodes[0]->network.flood_block (block); } TEST (node_config, random_rep) { auto path (nano::unique_path ()); - nano::logging logging1; - logging1.init (path); - nano::node_config config1 (100, logging1); + nano::node_config config1 (100); auto rep (config1.random_representative ()); ASSERT_NE (config1.preconfigured_representatives.end (), std::find (config1.preconfigured_representatives.begin (), config1.preconfigured_representatives.end (), rep)); } -TEST (node, fork_publish) +TEST (node, expire) { std::weak_ptr node0; { @@ -564,45 +524,51 @@ TEST (node, fork_publish) node0 = system.nodes[0]; auto & node1 (*system.nodes[0]); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - nano::keypair key1; - nano::send_block_builder builder; - auto send1 = builder.make_block () - .previous (nano::dev::genesis->hash ()) - .destination (key1.pub) - .balance (nano::dev::constants.genesis_amount - 100) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (0) - .build_shared (); - node1.work_generate_blocking (*send1); - nano::keypair key2; - auto send2 = builder.make_block () - .previous (nano::dev::genesis->hash ()) - .destination (key2.pub) - .balance (nano::dev::constants.genesis_amount - 100) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (0) - .build_shared (); - node1.work_generate_blocking (*send2); - node1.process_active (send1); - node1.block_processor.flush (); - ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); - auto election (node1.active.election (send1->qualified_root ())); - ASSERT_NE (nullptr, election); - // Wait until the genesis rep activated & makes vote - ASSERT_TIMELY_EQ (1s, election->votes ().size (), 2); - node1.process_active (send2); - node1.block_processor.flush (); - auto votes1 (election->votes ()); - auto existing1 (votes1.find (nano::dev::genesis_key.pub)); - ASSERT_NE (votes1.end (), existing1); - ASSERT_EQ (send1->hash (), existing1->second.hash); - auto winner (*election->tally ().begin ()); - ASSERT_EQ (*send1, *winner.second); - ASSERT_EQ (nano::dev::constants.genesis_amount - 100, winner.first); } ASSERT_TRUE (node0.expired ()); } +TEST (node, fork_publish) +{ + nano::test::system system (1); + auto & node1 (*system.nodes[0]); + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + nano::keypair key1; + nano::send_block_builder builder; + auto send1 = builder.make_block () + .previous (nano::dev::genesis->hash ()) + .destination (key1.pub) + .balance (nano::dev::constants.genesis_amount - 100) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (0) + .build (); + node1.work_generate_blocking (*send1); + nano::keypair key2; + auto send2 = builder.make_block () + .previous (nano::dev::genesis->hash ()) + .destination (key2.pub) + .balance (nano::dev::constants.genesis_amount - 100) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (0) + .build (); + node1.work_generate_blocking (*send2); + node1.process_active (send1); + ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); + auto election (node1.active.election (send1->qualified_root ())); + ASSERT_NE (nullptr, election); + // Wait until the genesis rep activated & makes vote + ASSERT_TIMELY_EQ (1s, election->votes ().size (), 2); + node1.process_active (send2); + ASSERT_TIMELY (5s, node1.active.active (*send2)); + auto votes1 (election->votes ()); + auto existing1 (votes1.find (nano::dev::genesis_key.pub)); + ASSERT_NE (votes1.end (), existing1); + ASSERT_EQ (send1->hash (), existing1->second.hash); + auto winner (*election->tally ().begin ()); + ASSERT_EQ (*send1, *winner.second); + ASSERT_EQ (nano::dev::constants.genesis_amount - 100, winner.first); +} + // In test case there used to be a race condition, it was worked around in:. // https://github.com/nanocurrency/nano-node/pull/4091 // The election and the processing of block send2 happen in parallel. @@ -626,7 +592,7 @@ TEST (node, fork_publish_inactive) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) @@ -634,7 +600,7 @@ TEST (node, fork_publish_inactive) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (send1->block_work ()) - .build_shared (); + .build (); node.process_active (send1); ASSERT_TIMELY (5s, node.block (send1->hash ())); @@ -642,12 +608,17 @@ TEST (node, fork_publish_inactive) std::shared_ptr election; ASSERT_TIMELY (5s, election = node.active.election (send1->qualified_root ())); - ASSERT_EQ (nano::process_result::fork, node.process_local (send2).value ().code); + ASSERT_EQ (nano::block_status::fork, node.process_local (send2).value ()); + + ASSERT_TIMELY_EQ (5s, election->blocks ().size (), 2); + + auto find_block = [&election] (nano::block_hash hash_a) -> bool { + auto blocks = election->blocks (); + return blocks.end () != blocks.find (hash_a); + }; + ASSERT_TRUE (find_block (send1->hash ())); + ASSERT_TRUE (find_block (send2->hash ())); - auto blocks = election->blocks (); - ASSERT_TIMELY_EQ (5s, blocks.size (), 2); - ASSERT_NE (blocks.end (), blocks.find (send1->hash ())); - ASSERT_NE (blocks.end (), blocks.find (send2->hash ())); ASSERT_EQ (election->winner ()->hash (), send1->hash ()); ASSERT_NE (election->winner ()->hash (), send2->hash ()); } @@ -668,25 +639,24 @@ TEST (node, fork_keep) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) .destination (key2.pub) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send1); - node1.block_processor.flush (); node2.process_active (send1); - node2.block_processor.flush (); ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); ASSERT_TIMELY_EQ (5s, 1, node2.active.size ()); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + // Fill node with forked blocks node1.process_active (send2); - node1.block_processor.flush (); + ASSERT_TIMELY (5s, node1.active.active (*send2)); node2.process_active (send2); - node2.block_processor.flush (); + ASSERT_TIMELY (5s, node2.active.active (*send2)); auto election1 (node2.active.election (nano::qualified_root (nano::dev::genesis->hash (), nano::dev::genesis->hash ()))); ASSERT_NE (nullptr, election1); ASSERT_EQ (1, election1->votes ().size ()); @@ -700,8 +670,8 @@ TEST (node, fork_keep) auto winner (*election1->tally ().begin ()); ASSERT_EQ (*send1, *winner.second); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, winner.first); - ASSERT_TRUE (node1.store.block.exists (transaction0, send1->hash ())); - ASSERT_TRUE (node2.store.block.exists (transaction1, send1->hash ())); + ASSERT_TRUE (node1.ledger.block_exists (transaction0, send1->hash ())); + ASSERT_TRUE (node2.ledger.block_exists (transaction1, send1->hash ())); } TEST (node, fork_flip) @@ -718,7 +688,7 @@ TEST (node, fork_flip) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::publish publish1{ nano::dev::network_params.network, send1 }; nano::keypair key2; auto send2 = builder.make_block () @@ -727,21 +697,20 @@ TEST (node, fork_flip) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::publish publish2{ nano::dev::network_params.network, send2 }; auto ignored_channel{ std::make_shared (node1, std::weak_ptr ()) }; node1.network.inbound (publish1, ignored_channel); - node1.block_processor.flush (); node2.network.inbound (publish2, ignored_channel); - node2.block_processor.flush (); ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); ASSERT_TIMELY_EQ (5s, 1, node2.active.size ()); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + // Fill nodes with forked blocks node1.network.inbound (publish2, ignored_channel); - node1.block_processor.flush (); + ASSERT_TIMELY (5s, node1.active.active (*send2)); node2.network.inbound (publish1, ignored_channel); - node2.block_processor.flush (); + ASSERT_TIMELY (5s, node2.active.active (*send1)); auto election1 (node2.active.election (nano::qualified_root (nano::dev::genesis->hash (), nano::dev::genesis->hash ()))); ASSERT_NE (nullptr, election1); ASSERT_EQ (1, election1->votes ().size ()); @@ -756,12 +725,13 @@ TEST (node, fork_flip) ASSERT_FALSE (node2.ledger.block_or_pruned_exists (publish2.block->hash ())); } +// Test that more than one block can be rolled back TEST (node, fork_multi_flip) { auto type = nano::transport::transport_type::tcp; nano::test::system system; nano::node_flags node_flags; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node1 (*system.add_node (node_config, node_flags, type)); node_config.peering_port = system.get_available_port (); @@ -775,8 +745,7 @@ TEST (node, fork_multi_flip) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - nano::publish publish1{ nano::dev::network_params.network, send1 }; + .build (); nano::keypair key2; auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) @@ -784,47 +753,27 @@ TEST (node, fork_multi_flip) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - nano::publish publish2{ nano::dev::network_params.network, send2 }; + .build (); auto send3 = builder.make_block () - .previous (publish2.block->hash ()) + .previous (send2->hash ()) .destination (key2.pub) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (publish2.block->hash ())) - .build_shared (); - nano::publish publish3{ nano::dev::network_params.network, send3 }; - auto channel1 = std::make_shared (node1); - auto channel2 = std::make_shared (node2); - node1.network.inbound (publish1, channel1); - node2.network.inbound (publish2, channel2); - node2.network.inbound (publish3, channel2); - node1.block_processor.flush (); - node2.block_processor.flush (); - ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); - ASSERT_TIMELY_EQ (5s, 1, node2.active.size ()); - system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + .work (*system.work.generate (send2->hash ())) + .build (); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (node1.store.tx_begin_write (), send1)); + // Node2 has two blocks that will be rolled back by node1's vote + ASSERT_EQ (nano::block_status::progress, node2.ledger.process (node2.store.tx_begin_write (), send2)); + ASSERT_EQ (nano::block_status::progress, node2.ledger.process (node2.store.tx_begin_write (), send3)); + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); // Insert voting key in to node1 - node1.network.inbound (publish2, channel1); - node1.network.inbound (publish3, channel1); - node1.block_processor.flush (); - node2.network.inbound (publish1, channel2); - node2.block_processor.flush (); - ASSERT_TIMELY (5s, node2.active.election (nano::qualified_root (nano::dev::genesis->hash (), nano::dev::genesis->hash ()))); - auto election1 (node2.active.election (nano::qualified_root (nano::dev::genesis->hash (), nano::dev::genesis->hash ()))); - ASSERT_NE (nullptr, election1); - ASSERT_EQ (1, election1->votes ().size ()); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (publish1.block->hash ())); - ASSERT_TRUE (node2.ledger.block_or_pruned_exists (publish2.block->hash ())); - ASSERT_TRUE (node2.ledger.block_or_pruned_exists (publish3.block->hash ())); - ASSERT_TIMELY (10s, node2.ledger.block_or_pruned_exists (publish1.block->hash ())); - auto winner (*election1->tally ().begin ()); - ASSERT_EQ (*publish1.block, *winner.second); + auto election = nano::test::start_election (system, node2, send2->hash ()); + ASSERT_NE (nullptr, election); + ASSERT_TIMELY (5s, node2.ledger.block_or_pruned_exists (send1->hash ())); + ASSERT_TRUE (nano::test::block_or_pruned_none_exists (node2, { send2, send3 })); + auto winner = *election->tally ().begin (); + ASSERT_EQ (*send1, *winner.second); ASSERT_EQ (nano::dev::constants.genesis_amount - 100, winner.first); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (publish1.block->hash ())); - ASSERT_TRUE (node2.ledger.block_or_pruned_exists (publish1.block->hash ())); - ASSERT_FALSE (node2.ledger.block_or_pruned_exists (publish2.block->hash ())); - ASSERT_FALSE (node2.ledger.block_or_pruned_exists (publish3.block->hash ())); } // Blocks that are no longer actively being voted on should be able to be evicted through bootstrapping. @@ -834,13 +783,13 @@ TEST (node, fork_bootstrap_flip) nano::test::system system; nano::test::system system0; nano::test::system system1; - nano::node_config config0{ system.get_available_port (), system0.logging }; + nano::node_config config0{ system.get_available_port () }; config0.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags node_flags; node_flags.disable_bootstrap_bulk_push_client = true; node_flags.disable_lazy_bootstrap = true; auto & node1 = *system0.add_node (config0, node_flags); - nano::node_config config1 (system.get_available_port (), system1.logging); + nano::node_config config1 (system.get_available_port ()); auto & node2 = *system1.add_node (config1, node_flags); system0.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); nano::block_hash latest = node1.latest (nano::dev::genesis_key.pub); @@ -852,7 +801,7 @@ TEST (node, fork_bootstrap_flip) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system0.work.generate (latest)) - .build_shared (); + .build (); nano::keypair key2; auto send2 = builder.make_block () .previous (latest) @@ -860,11 +809,11 @@ TEST (node, fork_bootstrap_flip) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system0.work.generate (latest)) - .build_shared (); + .build (); // Insert but don't rebroadcast, simulating settled blocks - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (node1.store.tx_begin_write (), *send1).code); - ASSERT_EQ (nano::process_result::progress, node2.ledger.process (node2.store.tx_begin_write (), *send2).code); - ASSERT_TRUE (node2.store.block.exists (node2.store.tx_begin_read (), send2->hash ())); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (node1.store.tx_begin_write (), send1)); + ASSERT_EQ (nano::block_status::progress, node2.ledger.process (node2.store.tx_begin_write (), send2)); + ASSERT_TRUE (node2.ledger.block_exists (node2.store.tx_begin_read (), send2->hash ())); node2.bootstrap_initiator.bootstrap (node1.network.endpoint ()); // Additionally add new peer to confirm & replace bootstrap block auto again (true); system0.deadline_set (50s); @@ -873,7 +822,7 @@ TEST (node, fork_bootstrap_flip) { ASSERT_NO_ERROR (system0.poll ()); ASSERT_NO_ERROR (system1.poll ()); - again = !node2.store.block.exists (node2.store.tx_begin_read (), send1->hash ()); + again = !node2.ledger.block_exists (node2.store.tx_begin_read (), send1->hash ()); } } @@ -892,7 +841,7 @@ TEST (node, fork_open) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::publish publish1{ nano::dev::network_params.network, send1 }; auto channel1 = std::make_shared (node); node.network.inbound (publish1, channel1); @@ -912,7 +861,7 @@ TEST (node, fork_open) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); nano::publish publish2{ nano::dev::network_params.network, open1 }; node.network.inbound (publish2, channel1); ASSERT_TIMELY_EQ (5s, 1, node.active.size ()); @@ -924,7 +873,7 @@ TEST (node, fork_open) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); nano::publish publish3{ nano::dev::network_params.network, open2 }; node.network.inbound (publish3, channel1); ASSERT_TIMELY (5s, (election = node.active.election (publish3.block->qualified_root ())) != nullptr); @@ -959,7 +908,7 @@ TEST (node, fork_open_flip) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send1); // We should be keeping this block @@ -970,7 +919,7 @@ TEST (node, fork_open_flip) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); // create a fork of block open1, this block will lose the election auto open2 = builder.make_block () @@ -979,7 +928,7 @@ TEST (node, fork_open_flip) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); + .build (); ASSERT_FALSE (*open1 == *open2); // give block open1 to node1, manually trigger an election for open1 and ensure it is in the ledger @@ -1025,9 +974,9 @@ TEST (node, fork_open_flip) // check the correct blocks are in the ledgers auto transaction1 (node1.store.tx_begin_read ()); auto transaction2 (node2.store.tx_begin_read ()); - ASSERT_TRUE (node1.store.block.exists (transaction1, open1->hash ())); - ASSERT_TRUE (node2.store.block.exists (transaction2, open1->hash ())); - ASSERT_FALSE (node2.store.block.exists (transaction2, open2->hash ())); + ASSERT_TRUE (node1.ledger.block_exists (transaction1, open1->hash ())); + ASSERT_TRUE (node2.ledger.block_exists (transaction2, open1->hash ())); + ASSERT_FALSE (node2.ledger.block_exists (transaction2, open2->hash ())); } TEST (node, coherent_observer) @@ -1036,7 +985,7 @@ TEST (node, coherent_observer) auto & node1 (*system.nodes[0]); node1.observers.blocks.add ([&node1] (nano::election_status const & status_a, std::vector const &, nano::account const &, nano::uint128_t const &, bool, bool) { auto transaction (node1.store.tx_begin_read ()); - ASSERT_TRUE (node1.store.block.exists (transaction, status_a.winner->hash ())); + ASSERT_TRUE (node1.ledger.block_exists (transaction, status_a.winner->hash ())); }); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); nano::keypair key; @@ -1074,9 +1023,9 @@ TEST (node, fork_no_vote_quorum) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (block->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node2.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node3.process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); + ASSERT_EQ (nano::block_status::progress, node2.process (send1)); + ASSERT_EQ (nano::block_status::progress, node3.process (send1)); auto key2 (system.wallet (2)->deterministic_insert ()); auto send2 = nano::send_block_builder () .previous (block->hash ()) @@ -1084,7 +1033,7 @@ TEST (node, fork_no_vote_quorum) .balance ((nano::dev::constants.genesis_amount / 4) - (node1.config.receive_minimum.number () * 2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (block->hash ())) - .build_shared (); + .build (); nano::raw_key key3; auto transaction (system.wallet (1)->wallets.tx_begin_read ()); ASSERT_FALSE (system.wallet (1)->store.fetch (transaction, key1, key3)); @@ -1141,7 +1090,7 @@ TEST (node, DISABLED_fork_pre_confirm) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); auto block3 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (node0.latest (nano::dev::genesis_key.pub)) @@ -1150,7 +1099,7 @@ TEST (node, DISABLED_fork_pre_confirm) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node0.work_generate_blocking (*block2); node0.work_generate_blocking (*block3); node0.process_active (block2); @@ -1179,7 +1128,7 @@ TEST (node, DISABLED_fork_stale) auto channel = nano::test::establish_tcp (system1, node2, node1.network.endpoint ()); auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector ()); - node2.rep_crawler.response (channel, vote); + ASSERT_TRUE (node2.rep_crawler.process (vote, channel)); nano::keypair key1; nano::keypair key2; nano::state_block_builder builder; @@ -1191,7 +1140,7 @@ TEST (node, DISABLED_fork_stale) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send3); node1.process_active (send3); system2.deadline_set (10s); @@ -1208,7 +1157,7 @@ TEST (node, DISABLED_fork_stale) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send1); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -1218,13 +1167,13 @@ TEST (node, DISABLED_fork_stale) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*send2); { auto transaction1 (node1.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction1, *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction1, send1)); auto transaction2 (node2.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node2.ledger.process (transaction2, *send2).code); + ASSERT_EQ (nano::block_status::progress, node2.ledger.process (transaction2, send2)); } node1.process_active (send1); node1.process_active (send2); @@ -1246,7 +1195,7 @@ TEST (node, DISABLED_broadcast_elected) auto type = nano::transport::transport_type::tcp; nano::node_flags node_flags; nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node0 = system.add_node (node_config, node_flags, type); node_config.peering_port = system.get_available_port (); @@ -1261,66 +1210,66 @@ TEST (node, DISABLED_broadcast_elected) auto transaction0 (node0->store.tx_begin_write ()); auto transaction1 (node1->store.tx_begin_write ()); auto transaction2 (node2->store.tx_begin_write ()); - auto fund_big = *builder.send () - .previous (nano::dev::genesis->hash ()) - .destination (rep_big.pub) - .balance (nano::Gxrb_ratio * 5) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build (); - auto open_big = *builder.open () - .source (fund_big.hash ()) - .representative (rep_big.pub) - .account (rep_big.pub) - .sign (rep_big.prv, rep_big.pub) - .work (*system.work.generate (rep_big.pub)) - .build (); - auto fund_small = *builder.send () - .previous (fund_big.hash ()) - .destination (rep_small.pub) - .balance (nano::Gxrb_ratio * 2) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (fund_big.hash ())) - .build (); - auto open_small = *builder.open () - .source (fund_small.hash ()) - .representative (rep_small.pub) - .account (rep_small.pub) - .sign (rep_small.prv, rep_small.pub) - .work (*system.work.generate (rep_small.pub)) - .build (); - auto fund_other = *builder.send () - .previous (fund_small.hash ()) - .destination (rep_other.pub) - .balance (nano::Gxrb_ratio) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (fund_small.hash ())) - .build (); - auto open_other = *builder.open () - .source (fund_other.hash ()) - .representative (rep_other.pub) - .account (rep_other.pub) - .sign (rep_other.prv, rep_other.pub) - .work (*system.work.generate (rep_other.pub)) - .build (); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, fund_big).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, fund_big).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, fund_big).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, open_big).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, open_big).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, open_big).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, fund_small).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, fund_small).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, fund_small).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, open_small).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, open_small).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, open_small).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, fund_other).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, fund_other).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, fund_other).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction0, open_other).code); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction1, open_other).code); - ASSERT_EQ (nano::process_result::progress, node2->ledger.process (transaction2, open_other).code); + auto fund_big = builder.send () + .previous (nano::dev::genesis->hash ()) + .destination (rep_big.pub) + .balance (nano::Gxrb_ratio * 5) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + auto open_big = builder.open () + .source (fund_big->hash ()) + .representative (rep_big.pub) + .account (rep_big.pub) + .sign (rep_big.prv, rep_big.pub) + .work (*system.work.generate (rep_big.pub)) + .build (); + auto fund_small = builder.send () + .previous (fund_big->hash ()) + .destination (rep_small.pub) + .balance (nano::Gxrb_ratio * 2) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (fund_big->hash ())) + .build (); + auto open_small = builder.open () + .source (fund_small->hash ()) + .representative (rep_small.pub) + .account (rep_small.pub) + .sign (rep_small.prv, rep_small.pub) + .work (*system.work.generate (rep_small.pub)) + .build (); + auto fund_other = builder.send () + .previous (fund_small->hash ()) + .destination (rep_other.pub) + .balance (nano::Gxrb_ratio) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (fund_small->hash ())) + .build (); + auto open_other = builder.open () + .source (fund_other->hash ()) + .representative (rep_other.pub) + .account (rep_other.pub) + .sign (rep_other.prv, rep_other.pub) + .work (*system.work.generate (rep_other.pub)) + .build (); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, fund_big)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, fund_big)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, fund_big)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, open_big)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, open_big)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, open_big)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, fund_small)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, fund_small)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, fund_small)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, open_small)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, open_small)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, open_small)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, fund_other)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, fund_other)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, fund_other)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction0, open_other)); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction1, open_other)); + ASSERT_EQ (nano::block_status::progress, node2->ledger.process (transaction2, open_other)); } // Confirm blocks to allow voting for (auto & node : system.nodes) @@ -1343,7 +1292,7 @@ TEST (node, DISABLED_broadcast_elected) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (node2->latest (nano::dev::genesis_key.pub))) - .build_shared (); + .build (); // A copy is necessary to avoid data races during ledger processing, which sets the sideband auto fork0_copy (std::make_shared (*fork0)); node0->process_active (fork0); @@ -1354,7 +1303,7 @@ TEST (node, DISABLED_broadcast_elected) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (node2->latest (nano::dev::genesis_key.pub))) - .build_shared (); + .build (); system.wallet (2)->insert_adhoc (rep_small.prv); node2->process_active (fork1); ASSERT_TIMELY (10s, node0->ledger.block_or_pruned_exists (fork0->hash ()) && node1->ledger.block_or_pruned_exists (fork0->hash ())); @@ -1372,45 +1321,45 @@ TEST (node, DISABLED_broadcast_elected) TEST (node, rep_self_vote) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.online_weight_minimum = std::numeric_limits::max (); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node0 = system.add_node (node_config); nano::keypair rep_big; nano::block_builder builder; - auto fund_big = *builder.send () - .previous (nano::dev::genesis->hash ()) - .destination (rep_big.pub) - .balance (nano::uint128_t{ "0xb0000000000000000000000000000000" }) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build (); - auto open_big = *builder.open () - .source (fund_big.hash ()) - .representative (rep_big.pub) - .account (rep_big.pub) - .sign (rep_big.prv, rep_big.pub) - .work (*system.work.generate (rep_big.pub)) - .build (); - ASSERT_EQ (nano::process_result::progress, node0->process (fund_big).code); - ASSERT_EQ (nano::process_result::progress, node0->process (open_big).code); + auto fund_big = builder.send () + .previous (nano::dev::genesis->hash ()) + .destination (rep_big.pub) + .balance (nano::uint128_t{ "0xb0000000000000000000000000000000" }) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + auto open_big = builder.open () + .source (fund_big->hash ()) + .representative (rep_big.pub) + .account (rep_big.pub) + .sign (rep_big.prv, rep_big.pub) + .work (*system.work.generate (rep_big.pub)) + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (fund_big)); + ASSERT_EQ (nano::block_status::progress, node0->process (open_big)); // Confirm both blocks, allowing voting on the upcoming block - node0->start_election (node0->block (open_big.hash ())); + node0->start_election (node0->block (open_big->hash ())); std::shared_ptr election; - ASSERT_TIMELY (5s, election = node0->active.election (open_big.qualified_root ())); + ASSERT_TIMELY (5s, election = node0->active.election (open_big->qualified_root ())); election->force_confirm (); system.wallet (0)->insert_adhoc (rep_big.prv); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); ASSERT_EQ (system.wallet (0)->wallets.reps ().voting, 2); auto block0 = builder.send () - .previous (fund_big.hash ()) + .previous (fund_big->hash ()) .destination (rep_big.pub) .balance (nano::uint128_t ("0x60000000000000000000000000000000")) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (fund_big.hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*block0).code); + .work (*system.work.generate (fund_big->hash ())) + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (block0)); auto & active = node0->active; auto & scheduler = node0->scheduler; scheduler.priority.activate (nano::dev::genesis_key.pub, node0->store.tx_begin_read ()); @@ -1444,7 +1393,7 @@ TEST (node, DISABLED_bootstrap_no_publish) .build (); { auto transaction (node0->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *send0).code); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, send0)); } ASSERT_FALSE (node1->bootstrap_initiator.in_progress ()); node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); @@ -1470,10 +1419,10 @@ TEST (node, DISABLED_bootstrap_bulk_push) nano::test::system system; nano::test::system system0; nano::test::system system1; - nano::node_config config0 (system.get_available_port (), system0.logging); + nano::node_config config0 (system.get_available_port ()); config0.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node0 (system0.add_node (config0)); - nano::node_config config1 (system.get_available_port (), system1.logging); + nano::node_config config1 (system.get_available_port ()); config1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node1 (system1.add_node (config1)); nano::keypair key0; @@ -1484,8 +1433,8 @@ TEST (node, DISABLED_bootstrap_bulk_push) .balance (500) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*send0).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (send0)); ASSERT_FALSE (node0->bootstrap_initiator.in_progress ()); ASSERT_FALSE (node1->bootstrap_initiator.in_progress ()); @@ -1510,56 +1459,56 @@ TEST (node, DISABLED_bootstrap_bulk_push) TEST (node, bootstrap_fork_open) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); auto node0 = system.add_node (node_config); node_config.peering_port = system.get_available_port (); auto node1 = system.add_node (node_config); nano::keypair key0; nano::block_builder builder; - auto send0 = *builder.send () - .previous (nano::dev::genesis->hash ()) - .destination (key0.pub) - .balance (nano::dev::constants.genesis_amount - 500) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build (); - auto open0 = *builder.open () - .source (send0.hash ()) - .representative (1) - .account (key0.pub) - .sign (key0.prv, key0.pub) - .work (*system.work.generate (key0.pub)) - .build (); - auto open1 = *builder.open () - .source (send0.hash ()) - .representative (2) - .account (key0.pub) - .sign (key0.prv, key0.pub) - .work (*system.work.generate (key0.pub)) - .build (); + auto send0 = builder.send () + .previous (nano::dev::genesis->hash ()) + .destination (key0.pub) + .balance (nano::dev::constants.genesis_amount - 500) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + auto open0 = builder.open () + .source (send0->hash ()) + .representative (1) + .account (key0.pub) + .sign (key0.prv, key0.pub) + .work (*system.work.generate (key0.pub)) + .build (); + auto open1 = builder.open () + .source (send0->hash ()) + .representative (2) + .account (key0.pub) + .sign (key0.prv, key0.pub) + .work (*system.work.generate (key0.pub)) + .build (); // Both know about send0 - ASSERT_EQ (nano::process_result::progress, node0->process (send0).code); - ASSERT_EQ (nano::process_result::progress, node1->process (send0).code); + ASSERT_EQ (nano::block_status::progress, node0->process (send0)); + ASSERT_EQ (nano::block_status::progress, node1->process (send0)); // Confirm send0 to allow starting and voting on the following blocks for (auto node : system.nodes) { node->start_election (node->block (node->latest (nano::dev::genesis_key.pub))); - ASSERT_TIMELY (1s, node->active.election (send0.qualified_root ())); - auto election = node->active.election (send0.qualified_root ()); + ASSERT_TIMELY (1s, node->active.election (send0->qualified_root ())); + auto election = node->active.election (send0->qualified_root ()); ASSERT_NE (nullptr, election); election->force_confirm (); ASSERT_TIMELY (2s, node->active.empty ()); } - ASSERT_TIMELY (3s, node0->block_confirmed (send0.hash ())); + ASSERT_TIMELY (3s, node0->block_confirmed (send0->hash ())); // They disagree about open0/open1 - ASSERT_EQ (nano::process_result::progress, node0->process (open0).code); - ASSERT_EQ (nano::process_result::progress, node1->process (open1).code); + ASSERT_EQ (nano::block_status::progress, node0->process (open0)); + ASSERT_EQ (nano::block_status::progress, node1->process (open1)); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - ASSERT_FALSE (node1->ledger.block_or_pruned_exists (open0.hash ())); + ASSERT_FALSE (node1->ledger.block_or_pruned_exists (open0->hash ())); ASSERT_FALSE (node1->bootstrap_initiator.in_progress ()); node1->bootstrap_initiator.bootstrap (node0->network.endpoint (), false); ASSERT_TIMELY (1s, node1->active.empty ()); - ASSERT_TIMELY (10s, !node1->ledger.block_or_pruned_exists (open1.hash ()) && node1->ledger.block_or_pruned_exists (open0.hash ())); + ASSERT_TIMELY (10s, !node1->ledger.block_or_pruned_exists (open1->hash ()) && node1->ledger.block_or_pruned_exists (open0->hash ())); } // Unconfirmed blocks from bootstrap should be confirmed @@ -1580,8 +1529,8 @@ TEST (node, bootstrap_confirm_frontiers) .balance (nano::dev::constants.genesis_amount - 500) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node0->process (*send0).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node0->process (send0)); // each system only has one node, so there should be no bootstrapping going on ASSERT_FALSE (node0->bootstrap_initiator.in_progress ()); @@ -1619,7 +1568,7 @@ TEST (node, unconfirmed_send) // firstly, send two units from node1 to node2 and expect that both nodes see the block as confirmed // (node1 will start an election for it, vote on it and node2 gets synced up) - auto send1 = wallet1->send_action (nano::dev::genesis->account (), key2.pub, 2 * nano::Mxrb_ratio); + auto send1 = wallet1->send_action (nano::dev::genesis_key.pub, key2.pub, 2 * nano::Mxrb_ratio); ASSERT_TIMELY (5s, node1.block_confirmed (send1->hash ())); ASSERT_TIMELY (5s, node2.block_confirmed (send1->hash ())); @@ -1635,269 +1584,19 @@ TEST (node, unconfirmed_send) .previous (recv1->hash ()) .representative (nano::dev::genesis_key.pub) .balance (nano::Mxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (key2.prv, key2.pub) .work (*system.work.generate (recv1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node2.process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node2.process (send2)); - auto send3 = wallet2->send_action (key2.pub, nano::dev::genesis->account (), nano::Mxrb_ratio); + auto send3 = wallet2->send_action (key2.pub, nano::dev::genesis_key.pub, nano::Mxrb_ratio); ASSERT_TIMELY (5s, node2.block_confirmed (send2->hash ())); ASSERT_TIMELY (5s, node1.block_confirmed (send2->hash ())); ASSERT_TIMELY (5s, node2.block_confirmed (send3->hash ())); ASSERT_TIMELY (5s, node1.block_confirmed (send3->hash ())); ASSERT_TIMELY_EQ (5s, node2.ledger.cache.cemented_count, 7); - ASSERT_TIMELY_EQ (5s, node1.balance (nano::dev::genesis->account ()), nano::dev::constants.genesis_amount); -} - -// Test that nodes can track nodes that have rep weight for priority broadcasting -TEST (node, rep_list) -{ - nano::test::system system (2); - auto & node1 (*system.nodes[1]); - auto wallet0 (system.wallet (0)); - auto wallet1 (system.wallet (1)); - // Node0 has a rep - wallet0->insert_adhoc (nano::dev::genesis_key.prv); - nano::keypair key1; - // Broadcast a confirm so others should know this is a rep node - wallet0->send_action (nano::dev::genesis_key.pub, key1.pub, nano::Mxrb_ratio); - ASSERT_EQ (0, node1.rep_crawler.representatives (1).size ()); - system.deadline_set (10s); - auto done (false); - while (!done) - { - auto reps = node1.rep_crawler.representatives (1); - if (!reps.empty ()) - { - if (!node1.ledger.weight (reps[0].account).is_zero ()) - { - done = true; - } - } - ASSERT_NO_ERROR (system.poll ()); - } -} - -TEST (node, rep_weight) -{ - nano::test::system system; - auto add_node = [&system] { - auto node = std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work); - node->start (); - system.nodes.push_back (node); - return node; - }; - auto & node = *add_node (); - auto & node1 = *add_node (); - auto & node2 = *add_node (); - auto & node3 = *add_node (); - nano::keypair keypair1; - nano::keypair keypair2; - nano::block_builder builder; - auto amount_pr (node.minimum_principal_weight () + 100); - auto amount_not_pr (node.minimum_principal_weight () - 100); - std::shared_ptr block1 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - amount_not_pr) - .link (keypair1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build (); - std::shared_ptr block2 = builder - .state () - .account (keypair1.pub) - .previous (0) - .representative (keypair1.pub) - .balance (amount_not_pr) - .link (block1->hash ()) - .sign (keypair1.prv, keypair1.pub) - .work (*system.work.generate (keypair1.pub)) - .build (); - std::shared_ptr block3 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (block1->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - amount_not_pr - amount_pr) - .link (keypair2.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (block1->hash ())) - .build (); - std::shared_ptr block4 = builder - .state () - .account (keypair2.pub) - .previous (0) - .representative (keypair2.pub) - .balance (amount_pr) - .link (block3->hash ()) - .sign (keypair2.prv, keypair2.pub) - .work (*system.work.generate (keypair2.pub)) - .build (); - { - auto transaction = node.store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block1).code); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block2).code); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block3).code); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *block4).code); - } - ASSERT_TRUE (node.rep_crawler.representatives (1).empty ()); - std::shared_ptr channel1 = nano::test::establish_tcp (system, node, node1.network.endpoint ()); - ASSERT_NE (nullptr, channel1); - std::shared_ptr channel2 = nano::test::establish_tcp (system, node, node2.network.endpoint ()); - ASSERT_NE (nullptr, channel2); - std::shared_ptr channel3 = nano::test::establish_tcp (system, node, node3.network.endpoint ()); - ASSERT_NE (nullptr, channel3); - auto vote0 = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - auto vote1 = std::make_shared (keypair1.pub, keypair1.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - auto vote2 = std::make_shared (keypair2.pub, keypair2.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - node.rep_crawler.response (channel1, vote0); - node.rep_crawler.response (channel2, vote1); - node.rep_crawler.response (channel3, vote2); - ASSERT_TIMELY_EQ (5s, node.rep_crawler.representative_count (), 2); - // Make sure we get the rep with the most weight first - auto reps = node.rep_crawler.representatives (1); - ASSERT_EQ (1, reps.size ()); - ASSERT_EQ (node.balance (nano::dev::genesis_key.pub), node.ledger.weight (reps[0].account)); - ASSERT_EQ (nano::dev::genesis_key.pub, reps[0].account); - ASSERT_EQ (*channel1, reps[0].channel_ref ()); - ASSERT_TRUE (node.rep_crawler.is_pr (*channel1)); - ASSERT_FALSE (node.rep_crawler.is_pr (*channel2)); - ASSERT_TRUE (node.rep_crawler.is_pr (*channel3)); -} - -// Test that rep_crawler removes unreachable reps from its search results. -// This test creates three principal representatives (rep1, rep2, genesis_rep) and -// one node for searching them (searching_node). -TEST (node, rep_remove) -{ - nano::test::system system; - auto & searching_node = *system.add_node (); // will be used to find principal representatives - nano::keypair keys_rep1; // Principal representative 1 - nano::keypair keys_rep2; // Principal representative 2 - nano::block_builder builder; - - // Send enough nanos to Rep1 to make it a principal representative - std::shared_ptr send_to_rep1 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 2) - .link (keys_rep1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (nano::dev::genesis->hash ())) - .build (); - - // Receive by Rep1 - std::shared_ptr receive_rep1 = builder - .state () - .account (keys_rep1.pub) - .previous (0) - .representative (keys_rep1.pub) - .balance (searching_node.minimum_principal_weight () * 2) - .link (send_to_rep1->hash ()) - .sign (keys_rep1.prv, keys_rep1.pub) - .work (*system.work.generate (keys_rep1.pub)) - .build (); - - // Send enough nanos to Rep2 to make it a principal representative - std::shared_ptr send_to_rep2 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (send_to_rep1->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 4) - .link (keys_rep2.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (send_to_rep1->hash ())) - .build (); - - // Receive by Rep2 - std::shared_ptr receive_rep2 = builder - .state () - .account (keys_rep2.pub) - .previous (0) - .representative (keys_rep2.pub) - .balance (searching_node.minimum_principal_weight () * 2) - .link (send_to_rep2->hash ()) - .sign (keys_rep2.prv, keys_rep2.pub) - .work (*system.work.generate (keys_rep2.pub)) - .build (); - { - auto transaction = searching_node.store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, searching_node.ledger.process (transaction, *send_to_rep1).code); - ASSERT_EQ (nano::process_result::progress, searching_node.ledger.process (transaction, *receive_rep1).code); - ASSERT_EQ (nano::process_result::progress, searching_node.ledger.process (transaction, *send_to_rep2).code); - ASSERT_EQ (nano::process_result::progress, searching_node.ledger.process (transaction, *receive_rep2).code); - } - - // Create channel for Rep1 - auto channel_rep1 (std::make_shared (searching_node)); - - // Ensure Rep1 is found by the rep_crawler after receiving a vote from it - auto vote_rep1 = std::make_shared (keys_rep1.pub, keys_rep1.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - ASSERT_FALSE (searching_node.rep_crawler.response (channel_rep1, vote_rep1, true)); - ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 1); - auto reps (searching_node.rep_crawler.representatives (1)); - ASSERT_EQ (1, reps.size ()); - ASSERT_EQ (searching_node.minimum_principal_weight () * 2, searching_node.ledger.weight (reps[0].account)); - ASSERT_EQ (keys_rep1.pub, reps[0].account); - ASSERT_EQ (*channel_rep1, reps[0].channel_ref ()); - - // When rep1 disconnects then rep1 should not be found anymore - channel_rep1->close (); - ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 0); - - // Add working node for genesis representative - auto node_genesis_rep = system.add_node (nano::node_config (system.get_available_port (), system.logging)); - system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); - auto channel_genesis_rep (searching_node.network.find_node_id (node_genesis_rep->get_node_id ())); - ASSERT_NE (nullptr, channel_genesis_rep); - - // genesis_rep should be found as principal representative after receiving a vote from it - auto vote_genesis_rep = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - searching_node.rep_crawler.response (channel_genesis_rep, vote_genesis_rep, true); - ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 1); - - // Start a node for Rep2 and wait until it is connected - auto node_rep2 (std::make_shared (system.io_ctx, nano::unique_path (), nano::node_config (system.get_available_port (), system.logging), system.work)); - node_rep2->start (); - searching_node.network.tcp_channels.start_tcp (node_rep2->network.endpoint ()); - std::shared_ptr channel_rep2; - ASSERT_TIMELY (10s, (channel_rep2 = searching_node.network.tcp_channels.find_node_id (node_rep2->get_node_id ())) != nullptr); - - // Rep2 should be found as a principal representative after receiving a vote from it - auto vote_rep2 = std::make_shared (keys_rep2.pub, keys_rep2.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - ASSERT_FALSE (searching_node.rep_crawler.response (channel_rep2, vote_rep2, true)); - ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 2); - - // When Rep2 is stopped, it should not be found as principal representative anymore - node_rep2->stop (); - ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 1); - - // Now only genesisRep should be found: - reps = searching_node.rep_crawler.representatives (1); - ASSERT_EQ (nano::dev::genesis_key.pub, reps[0].account); - ASSERT_TIMELY_EQ (5s, searching_node.network.size (), 1); - auto list (searching_node.network.list (1)); - ASSERT_EQ (node_genesis_rep->network.endpoint (), list[0]->get_endpoint ()); -} - -TEST (node, rep_connection_close) -{ - nano::test::system system (2); - auto & node1 (*system.nodes[0]); - auto & node2 (*system.nodes[1]); - // Add working representative (node 2) - system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); - ASSERT_TIMELY_EQ (10s, node1.rep_crawler.representative_count (), 1); - node2.stop (); - // Remove representative with closed channel - ASSERT_TIMELY_EQ (10s, node1.rep_crawler.representative_count (), 0); + ASSERT_TIMELY_EQ (5s, node1.balance (nano::dev::genesis_key.pub), nano::dev::constants.genesis_amount); } // Test that nodes can disable representative voting @@ -1905,7 +1604,7 @@ TEST (node, no_voting) { nano::test::system system (1); auto & node0 (*system.nodes[0]); - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.enable_voting = false; system.add_node (node_config); @@ -2065,8 +1764,6 @@ TEST (node, online_reps) ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ()); } -namespace nano -{ TEST (node, online_reps_rep_crawler) { nano::test::system system; @@ -2079,14 +1776,11 @@ TEST (node, online_reps_rep_crawler) node1.vote_processor.vote_blocking (vote, std::make_shared (node1)); ASSERT_EQ (0, node1.online_reps.online ()); // After inserting to rep crawler - { - nano::lock_guard guard{ node1.rep_crawler.probable_reps_mutex }; - node1.rep_crawler.active.insert (nano::dev::genesis->hash ()); - } - node1.vote_processor.vote_blocking (vote, std::make_shared (node1)); + auto channel = std::make_shared (node1); + node1.rep_crawler.force_query (nano::dev::genesis->hash (), channel); + node1.vote_processor.vote_blocking (vote, channel); ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.online ()); } -} TEST (node, online_reps_election) { @@ -2105,9 +1799,8 @@ TEST (node, online_reps_election) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send1); - node1.block_processor.flush (); ASSERT_TIMELY_EQ (5s, 1, node1.active.size ()); // Process vote for ongoing election auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::milliseconds_since_epoch (), 0, std::vector{ send1->hash () }); @@ -2134,11 +1827,11 @@ TEST (node, block_confirm) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // A copy is necessary to avoid data races during ledger processing, which sets the sideband auto send1_copy = builder.make_block () .from (*send1) - .build_shared (); + .build (); auto hash1 = send1->hash (); auto hash2 = send1_copy->hash (); node1.block_processor.add (send1); @@ -2153,53 +1846,6 @@ TEST (node, block_confirm) ASSERT_TIMELY_EQ (10s, node1.active.recently_cemented.list ().size (), 1); } -TEST (node, block_arrival) -{ - nano::test::system system (1); - auto & node (*system.nodes[0]); - ASSERT_EQ (0, node.block_arrival.arrival.size ()); - nano::block_hash hash1 (1); - node.block_arrival.add (hash1); - ASSERT_EQ (1, node.block_arrival.arrival.size ()); - node.block_arrival.add (hash1); - ASSERT_EQ (1, node.block_arrival.arrival.size ()); - nano::block_hash hash2 (2); - node.block_arrival.add (hash2); - ASSERT_EQ (2, node.block_arrival.arrival.size ()); -} - -TEST (node, block_arrival_size) -{ - nano::test::system system (1); - auto & node (*system.nodes[0]); - auto time (std::chrono::steady_clock::now () - nano::block_arrival::arrival_time_min - std::chrono::seconds (5)); - nano::block_hash hash (0); - for (auto i (0); i < nano::block_arrival::arrival_size_min * 2; ++i) - { - node.block_arrival.arrival.push_back (nano::block_arrival_info{ time, hash }); - ++hash.qwords[0]; - } - ASSERT_EQ (nano::block_arrival::arrival_size_min * 2, node.block_arrival.arrival.size ()); - node.block_arrival.recent (0); - ASSERT_EQ (nano::block_arrival::arrival_size_min, node.block_arrival.arrival.size ()); -} - -TEST (node, block_arrival_time) -{ - nano::test::system system (1); - auto & node (*system.nodes[0]); - auto time (std::chrono::steady_clock::now ()); - nano::block_hash hash (0); - for (auto i (0); i < nano::block_arrival::arrival_size_min * 2; ++i) - { - node.block_arrival.arrival.push_back (nano::block_arrival_info{ time, hash }); - ++hash.qwords[0]; - } - ASSERT_EQ (nano::block_arrival::arrival_size_min * 2, node.block_arrival.arrival.size ()); - node.block_arrival.recent (0); - ASSERT_EQ (nano::block_arrival::arrival_size_min * 2, node.block_arrival.arrival.size ()); -} - TEST (node, confirm_quorum) { nano::test::system system (1); @@ -2215,8 +1861,8 @@ TEST (node, confirm_quorum) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, new_balance.number ()); ASSERT_TIMELY (2s, node1.active.election (send1->qualified_root ())); auto election = node1.active.election (send1->qualified_root ()); @@ -2229,7 +1875,7 @@ TEST (node, confirm_quorum) TEST (node, local_votes_cache) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; node_config.receive_minimum = nano::dev::constants.genesis_amount; auto & node (*system.add_node (node_config)); @@ -2242,7 +1888,7 @@ TEST (node, local_votes_cache) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) @@ -2251,7 +1897,7 @@ TEST (node, local_votes_cache) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); auto send3 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) @@ -2260,11 +1906,11 @@ TEST (node, local_votes_cache) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send2->hash ())) - .build_shared (); + .build (); { auto transaction (node.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (transaction, send2)); } // Confirm blocks to allow voting node.start_election (send2); @@ -2294,7 +1940,7 @@ TEST (node, local_votes_cache) // Max cache { auto transaction (node.store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (transaction, *send3).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (transaction, send3)); } nano::confirm_req message3{ nano::dev::network_params.network, send3->hash (), send3->root () }; for (auto i (0); i < 100; ++i) @@ -2317,7 +1963,7 @@ TEST (node, local_votes_cache) TEST (node, DISABLED_local_votes_cache_batch) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node (*system.add_node (node_config)); ASSERT_GE (node.network_params.voting.max_cache, 2); @@ -2331,8 +1977,8 @@ TEST (node, DISABLED_local_votes_cache_batch) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); node.confirmation_height_processor.add (send1); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = nano::state_block_builder () @@ -2343,8 +1989,8 @@ TEST (node, DISABLED_local_votes_cache_batch) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send2)); auto receive1 = nano::state_block_builder () .account (key1.pub) .previous (0) @@ -2353,8 +1999,8 @@ TEST (node, DISABLED_local_votes_cache_batch) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node.work_generate_blocking (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), receive1)); std::vector> batch{ { send2->hash (), send2->root () }, { receive1->hash (), receive1->root () } }; nano::confirm_req message{ nano::dev::network_params.network, batch }; auto channel = std::make_shared (node); @@ -2390,7 +2036,7 @@ TEST (node, DISABLED_local_votes_cache_batch) TEST (node, local_votes_cache_generate_new_vote) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node (*system.add_node (node_config)); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); @@ -2416,8 +2062,8 @@ TEST (node, local_votes_cache_generate_new_vote) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send1)); // One of the hashes is cached std::vector> roots_hashes{ std::make_pair (nano::dev::genesis->hash (), nano::dev::genesis->root ()), std::make_pair (send1->hash (), send1->root ()) }; nano::confirm_req message2{ nano::dev::network_params.network, roots_hashes }; @@ -2443,7 +2089,7 @@ TEST (node, local_votes_cache_fork) node_flags.disable_lazy_bootstrap = true; node_flags.disable_legacy_bootstrap = true; node_flags.disable_wallet_bootstrap = true; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node1 (*system.add_node (node_config, node_flags)); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); @@ -2455,7 +2101,7 @@ TEST (node, local_votes_cache_fork) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send1_fork = nano::state_block_builder () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -2464,10 +2110,10 @@ TEST (node, local_votes_cache_fork) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); // Cache vote - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector (1, send1->hash ()))); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { send1 }, 0, 0); node1.vote_processor.vote (vote, std::make_shared (node1)); node1.history.add (send1->root (), send1->hash (), vote); auto votes2 (node1.history.votes (send1->root (), send1->hash ())); @@ -2477,7 +2123,6 @@ TEST (node, local_votes_cache_fork) node_config.peering_port = system.get_available_port (); auto & node2 (*system.add_node (node_config, node_flags)); node2.process_active (send1_fork); - node2.block_processor.flush (); ASSERT_TIMELY (5s, node2.ledger.block_or_pruned_exists (send1->hash ())); } @@ -2498,14 +2143,14 @@ TEST (node, vote_republish) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) .destination (key2.pub) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number () * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // process send1 first, this will make sure send1 goes into the ledger and an election is started node1.process_active (send1); @@ -2521,7 +2166,7 @@ TEST (node, vote_republish) ASSERT_FALSE (node1.block (send2->hash ())); // the vote causes the election to reach quorum and for the vote (and block?) to be published from node1 to node2 - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, std::vector{ send2->hash () })); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { send2 }); node1.vote_processor.vote (vote, std::make_shared (node1)); // FIXME: there is a race condition here, if the vote arrives before the block then the vote is wasted and the test fails @@ -2556,9 +2201,9 @@ TEST (node, vote_by_hash_bundle) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); blocks.push_back (block); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *blocks.back ()).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), blocks.back ())); for (auto i = 2; i < 200; ++i) { auto block = builder.make_block () @@ -2567,9 +2212,9 @@ TEST (node, vote_by_hash_bundle) .balance (nano::dev::constants.genesis_amount - i) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (blocks.back ()->hash ())) - .build_shared (); + .build (); blocks.push_back (block); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *blocks.back ()).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), blocks.back ())); } // Confirming last block will confirm whole chain and allow us to generate votes for those blocks later @@ -2616,14 +2261,14 @@ TEST (node, vote_by_hash_republish) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) .destination (key2.pub) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number () * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // give block send1 to node1 and check that an election for send1 starts on both nodes node1.process_active (send1); @@ -2638,7 +2283,7 @@ TEST (node, vote_by_hash_republish) // construct a vote for send2 in order to overturn send1 std::vector vote_blocks; vote_blocks.push_back (send2->hash ()); - auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, vote_blocks); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { vote_blocks }); node1.vote_processor.vote (vote, std::make_shared (node1)); // send2 should win on both nodes @@ -2666,22 +2311,22 @@ TEST (node, DISABLED_vote_by_hash_epoch_block_republish) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto epoch1 = nano::state_block_builder () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1.process_active (send1); ASSERT_TIMELY (5s, node2.active.active (*send1)); node1.active.publish (epoch1); std::vector vote_blocks; vote_blocks.push_back (epoch1->hash ()); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, vote_blocks)); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { vote_blocks }, 0, 0); ASSERT_TRUE (node1.active.active (*send1)); ASSERT_TRUE (node2.active.active (*send1)); node1.vote_processor.vote (vote, std::make_shared (node1)); @@ -2694,7 +2339,7 @@ TEST (node, DISABLED_vote_by_hash_epoch_block_republish) TEST (node, epoch_conflict_confirm) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node0 = *system.add_node (node_config); node_config.peering_port = system.get_available_port (); @@ -2710,7 +2355,7 @@ TEST (node, epoch_conflict_confirm) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto open = builder.make_block () .account (key.pub) .previous (0) @@ -2719,7 +2364,7 @@ TEST (node, epoch_conflict_confirm) .link (send->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); auto change = builder.make_block () .account (key.pub) .previous (open->hash ()) @@ -2728,7 +2373,7 @@ TEST (node, epoch_conflict_confirm) .link (0) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send->hash ()) @@ -2737,7 +2382,7 @@ TEST (node, epoch_conflict_confirm) .link (open->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send->hash ())) - .build_shared (); + .build (); auto epoch_open = builder.make_block () .account (change->root ().as_account ()) .previous (0) @@ -2746,7 +2391,7 @@ TEST (node, epoch_conflict_confirm) .link (node0.ledger.epoch_link (nano::epoch::epoch_1)) .sign (epoch_signer.prv, epoch_signer.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); + .build (); // Process initial blocks on node1 ASSERT_TRUE (nano::test::process (node1, { send, send2, open })); @@ -2806,18 +2451,18 @@ TEST (node, DISABLED_fork_invalid_block_signature) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .previous (nano::dev::genesis->hash ()) .destination (key2.pub) .balance (std::numeric_limits::max () - node1.config.receive_minimum.number () * 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2_corrupt (std::make_shared (*send2)); send2_corrupt->signature = nano::signature (123); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ send2->hash () })); - auto vote_corrupt (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ send2_corrupt->hash () })); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { send2 }, 0, 0); + auto vote_corrupt = nano::test::make_vote (nano::dev::genesis_key, { send2_corrupt }, 0, 0); node1.process_active (send1); ASSERT_TIMELY (5s, node1.block (send1->hash ())); @@ -2845,7 +2490,7 @@ TEST (node, fork_election_invalid_block_signature) .link (nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); auto send2 = builder.state () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -2854,7 +2499,7 @@ TEST (node, fork_election_invalid_block_signature) .link (nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); auto send3 = builder.state () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -2863,7 +2508,7 @@ TEST (node, fork_election_invalid_block_signature) .link (nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .sign (nano::dev::genesis_key.prv, 0) // Invalid signature - .build_shared (); + .build (); auto channel1 = std::make_shared (node1); node1.network.inbound (nano::publish{ nano::dev::network_params.network, send1 }, channel1); @@ -2895,7 +2540,7 @@ TEST (node, block_processor_signatures) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (latest)) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) @@ -2904,7 +2549,7 @@ TEST (node, block_processor_signatures) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); auto send3 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) @@ -2913,7 +2558,7 @@ TEST (node, block_processor_signatures) .link (key3.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (send2->hash ())) - .build_shared (); + .build (); // Invalid signature bit auto send4 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -2923,7 +2568,7 @@ TEST (node, block_processor_signatures) .link (key3.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (send3->hash ())) - .build_shared (); + .build (); send4->signature.bytes[32] ^= 0x1; // Invalid signature bit (force) auto send5 = builder.make_block () @@ -2934,7 +2579,7 @@ TEST (node, block_processor_signatures) .link (key3.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (send3->hash ())) - .build_shared (); + .build (); send5->signature.bytes[32] ^= 0x1; // Invalid signature to unchecked node1.unchecked.put (send5->previous (), nano::unchecked_info{ send5 }); @@ -2946,7 +2591,7 @@ TEST (node, block_processor_signatures) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node1.work_generate_blocking (key1.pub)) - .build_shared (); + .build (); auto receive2 = builder.make_block () .account (key2.pub) .previous (0) @@ -2955,7 +2600,7 @@ TEST (node, block_processor_signatures) .link (send2->hash ()) .sign (key2.prv, key2.pub) .work (*node1.work_generate_blocking (key2.pub)) - .build_shared (); + .build (); // Invalid private key auto receive3 = builder.make_block () .account (key3.pub) @@ -2965,7 +2610,7 @@ TEST (node, block_processor_signatures) .link (send3->hash ()) .sign (key2.prv, key3.pub) .work (*node1.work_generate_blocking (key3.pub)) - .build_shared (); + .build (); node1.process_active (send1); node1.process_active (send2); node1.process_active (send3); @@ -2997,12 +2642,11 @@ TEST (node, block_processor_reject_state) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); send1->signature.bytes[0] ^= 1; ASSERT_FALSE (node.ledger.block_or_pruned_exists (send1->hash ())); node.process_active (send1); - auto flushed = std::async (std::launch::async, [&node] { node.block_processor.flush (); }); - ASSERT_NE (std::future_status::timeout, flushed.wait_for (5s)); + ASSERT_TIMELY_EQ (5s, 1, node.stats.count (nano::stat::type::blockprocessor_result, nano::stat::detail::bad_signature)); ASSERT_FALSE (node.ledger.block_or_pruned_exists (send1->hash ())); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -3012,11 +2656,9 @@ TEST (node, block_processor_reject_state) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node.process_active (send2); - auto flushed2 = std::async (std::launch::async, [&node] { node.block_processor.flush (); }); - ASSERT_NE (std::future_status::timeout, flushed2.wait_for (5s)); - ASSERT_TRUE (node.ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_TIMELY (5s, node.ledger.block_or_pruned_exists (send2->hash ())); } TEST (node, block_processor_full) @@ -3025,7 +2667,7 @@ TEST (node, block_processor_full) nano::node_flags node_flags; node_flags.force_use_write_database_queue = true; node_flags.block_processor_full_size = 3; - auto & node = *system.add_node (nano::node_config (system.get_available_port (), system.logging), node_flags); + auto & node = *system.add_node (nano::node_config (system.get_available_port ()), node_flags); nano::state_block_builder builder; auto send1 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -3035,7 +2677,7 @@ TEST (node, block_processor_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -3044,7 +2686,7 @@ TEST (node, block_processor_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send3 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -3053,7 +2695,7 @@ TEST (node, block_processor_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node.block_processor.stop (); // Stop processing the block queue node.block_processor.add (send1); ASSERT_FALSE (node.block_processor.full ()); @@ -3070,7 +2712,7 @@ TEST (node, block_processor_half_full) nano::node_flags node_flags; node_flags.block_processor_full_size = 6; node_flags.force_use_write_database_queue = true; - auto & node = *system.add_node (nano::node_config (system.get_available_port (), system.logging), node_flags); + auto & node = *system.add_node (nano::node_config (system.get_available_port ()), node_flags); nano::state_block_builder builder; auto send1 = builder.make_block () .account (nano::dev::genesis_key.pub) @@ -3080,7 +2722,7 @@ TEST (node, block_processor_half_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send1->hash ()) @@ -3089,7 +2731,7 @@ TEST (node, block_processor_half_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); auto send3 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (send2->hash ()) @@ -3098,7 +2740,7 @@ TEST (node, block_processor_half_full) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send2->hash ())) - .build_shared (); + .build (); // The write guard prevents block processor doing any writes auto write_guard = node.write_database_queue.wait (nano::writer::testing); node.block_processor.add (send1); @@ -3123,7 +2765,7 @@ TEST (node, confirm_back) .balance (genesis_start_balance - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::state_block_builder builder; auto open = builder.make_block () .account (key.pub) @@ -3133,7 +2775,7 @@ TEST (node, confirm_back) .link (send1->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (key.pub) .previous (open->hash ()) @@ -3142,7 +2784,7 @@ TEST (node, confirm_back) .link (nano::dev::genesis_key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); + .build (); node.process_active (send1); node.process_active (open); node.process_active (send2); @@ -3151,7 +2793,7 @@ TEST (node, confirm_back) ASSERT_EQ (3, node.active.size ()); std::vector vote_blocks; vote_blocks.push_back (send2->hash ()); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_max, nano::vote::duration_max, vote_blocks)); + auto vote = nano::test::make_final_vote (nano::dev::genesis_key, { vote_blocks }); node.vote_processor.vote_blocking (vote, std::make_shared (node)); ASSERT_TIMELY (10s, node.active.empty ()); } @@ -3162,7 +2804,7 @@ TEST (node, peers) auto node1 (system.nodes[0]); ASSERT_TRUE (node1->network.empty ()); - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); system.nodes.push_back (node2); auto endpoint = node1->network.endpoint (); @@ -3212,7 +2854,7 @@ TEST (node, peer_cache_restart) nano::endpoint_key endpoint_key{ endpoint.address ().to_v6 ().to_bytes (), endpoint.port () }; auto path (nano::unique_path ()); { - auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), path, system.logging, system.work)); + auto node2 (std::make_shared (system.io_ctx, system.get_available_port (), path, system.work)); system.nodes.push_back (node2); auto & store = node2->store; { @@ -3232,7 +2874,7 @@ TEST (node, peer_cache_restart) { nano::node_flags node_flags; node_flags.read_only = true; - auto node3 (std::make_shared (system.io_ctx, system.get_available_port (), path, system.logging, system.work, node_flags)); + auto node3 (std::make_shared (system.io_ctx, system.get_available_port (), path, system.work, node_flags)); system.nodes.push_back (node3); // Check cached peers after restart node3->network.start (); @@ -3253,45 +2895,6 @@ TEST (node, peer_cache_restart) } } -TEST (node, unchecked_cleanup) -{ - nano::test::system system{}; - nano::node_flags node_flags{}; - node_flags.disable_unchecked_cleanup = true; - nano::keypair key{}; - auto & node = *system.add_node (node_flags); - auto open = nano::state_block_builder () - .account (key.pub) - .previous (0) - .representative (key.pub) - .balance (1) - .link (key.pub) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - std::vector bytes; - { - nano::vectorstream stream (bytes); - open->serialize (stream); - } - // Add to the blocks filter - // Should be cleared after unchecked cleanup - ASSERT_FALSE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); - node.process_active (open); - // Waits for the open block to get saved in the database - ASSERT_TIMELY_EQ (15s, 1, node.unchecked.count ()); - node.config.unchecked_cutoff_time = std::chrono::seconds (2); - ASSERT_EQ (1, node.unchecked.count ()); - std::this_thread::sleep_for (std::chrono::seconds (1)); - node.unchecked_cleanup (); - ASSERT_TRUE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); - ASSERT_EQ (1, node.unchecked.count ()); - std::this_thread::sleep_for (std::chrono::seconds (2)); - node.unchecked_cleanup (); - ASSERT_FALSE (node.network.publish_filter.apply (bytes.data (), bytes.size ())); - ASSERT_EQ (0, node.unchecked.count ()); -} - /** This checks that a node can be opened (without being blocked) when a write lock is held elsewhere */ TEST (node, dont_write_lock_node) { @@ -3300,7 +2903,7 @@ TEST (node, dont_write_lock_node) std::promise write_lock_held_promise; std::promise finished_promise; std::thread ([&path, &write_lock_held_promise, &finished_promise] () { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, path, nano::dev::constants, false, true); { nano::ledger_cache ledger_cache; @@ -3337,7 +2940,7 @@ TEST (node, bidirectional_tcp) node_flags.disable_legacy_bootstrap = true; node_flags.disable_lazy_bootstrap = true; node_flags.disable_wallet_bootstrap = true; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node1 = system.add_node (node_config, node_flags); node_config.peering_port = system.get_available_port (); @@ -3365,7 +2968,7 @@ TEST (node, bidirectional_tcp) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1->process_active (send1); ASSERT_TIMELY (10s, node1->ledger.block_or_pruned_exists (send1->hash ()) && node2->ledger.block_or_pruned_exists (send1->hash ())); // Test block confirmation from node 1 (add representative to node 1) @@ -3398,9 +3001,8 @@ TEST (node, bidirectional_tcp) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); node2->process_active (send2); - node2->block_processor.flush (); ASSERT_TIMELY (10s, node1->ledger.block_or_pruned_exists (send2->hash ()) && node2->ledger.block_or_pruned_exists (send2->hash ())); // Test block confirmation from node 2 (add representative to node 2) system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); @@ -3450,7 +3052,7 @@ TEST (node, rollback_vote_self) .balance (nano::dev::constants.genesis_amount - (nano::dev::constants.genesis_amount / 2)) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto open = builder.make_block () .account (key.pub) @@ -3460,24 +3062,24 @@ TEST (node, rollback_vote_self) .balance (nano::dev::constants.genesis_amount / 2) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); // send 1 raw auto send2 = builder.make_block () .from (*send1) .previous (send1->hash ()) - .balance (send1->balance ().number () - 1) + .balance (send1->balance_field ().value ().number () - 1) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); // fork of send2 block auto fork = builder.make_block () .from (*send2) - .balance (send1->balance ().number () - 2) + .balance (send1->balance_field ().value ().number () - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .build_shared (); + .build (); // Process and mark the first 2 blocks as confirmed to allow voting ASSERT_TRUE (nano::test::process (node, { send1, open })); @@ -3535,7 +3137,7 @@ TEST (node, rollback_vote_self) TEST (node, rollback_gap_source) { nano::test::system system; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node = *system.add_node (node_config); nano::state_block_builder builder; @@ -3548,7 +3150,7 @@ TEST (node, rollback_gap_source) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Side a of a forked open block receiving from send1 // This is a losing block auto fork1a = builder.make_block () @@ -3559,25 +3161,25 @@ TEST (node, rollback_gap_source) .balance (1) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); auto send2 = builder.make_block () .from (*send1) .previous (send1->hash ()) - .balance (send1->balance ().number () - 1) + .balance (send1->balance_field ().value ().number () - 1) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); // Side b of a forked open block receiving from send2. // This is the winning block auto fork1b = builder.make_block () .from (*fork1a) .link (send2->hash ()) .sign (key.prv, key.pub) - .build_shared (); + .build (); // Set 'node' up with losing block 'fork1a' - ASSERT_EQ (nano::process_result::progress, node.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*fork1a).code); + ASSERT_EQ (nano::block_status::progress, node.process (send1)); + ASSERT_EQ (nano::block_status::progress, node.process (fork1a)); // Node has 'fork1a' & doesn't have source 'send2' for winning 'fork1b' block ASSERT_EQ (nullptr, node.block (send2->hash ())); node.block_processor.force (fork1b); @@ -3590,7 +3192,7 @@ TEST (node, rollback_gap_source) node.process_active (fork1a); ASSERT_TIMELY (5s, node.block (fork1a->hash ()) != nullptr); // With send2 block in ledger election can start again to remove fork block - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); node.block_processor.force (fork1b); // Wait for new rollback ASSERT_TIMELY_EQ (5s, node.stats.count (nano::stat::type::rollback, nano::stat::detail::open), 2); @@ -3603,7 +3205,7 @@ TEST (node, rollback_gap_source) TEST (node, dependency_graph) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node = *system.add_node (config); @@ -3619,7 +3221,7 @@ TEST (node, dependency_graph) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Receive from genesis auto key1_open = builder.make_block () .account (key1.pub) @@ -3654,7 +3256,7 @@ TEST (node, dependency_graph) .from (*gen_receive) .previous (gen_receive->hash ()) .link (key2.pub) - .balance (gen_receive->balance ().number () - 2) + .balance (gen_receive->balance_field ().value ().number () - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (gen_receive->hash ())) .build (); @@ -3693,7 +3295,7 @@ TEST (node, dependency_graph) .from (*key2_send1) .previous (key2_send1->hash ()) .link (key1.pub) - .balance (key2_send1->balance ().number () - 1) + .balance (key2_send1->balance_field ().value ().number () - 1) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2_send1->hash ())) .build (); @@ -3702,7 +3304,7 @@ TEST (node, dependency_graph) .from (*key1_send1) .previous (key1_send1->hash ()) .link (key2_send2->hash ()) - .balance (key1_send1->balance ().number () + 1) + .balance (key1_send1->balance_field ().value ().number () + 1) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_send1->hash ())) .build (); @@ -3711,7 +3313,7 @@ TEST (node, dependency_graph) .from (*key1_receive) .previous (key1_receive->hash ()) .link (key3.pub) - .balance (key1_receive->balance ().number () - 1) + .balance (key1_receive->balance_field ().value ().number () - 1) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_receive->hash ())) .build (); @@ -3720,7 +3322,7 @@ TEST (node, dependency_graph) .from (*key3_open) .previous (key3_open->hash ()) .link (key1_send2->hash ()) - .balance (key3_open->balance ().number () + 1) + .balance (key3_open->balance_field ().value ().number () + 1) .sign (key3.prv, key3.pub) .work (*system.work.generate (key3_open->hash ())) .build (); @@ -3729,24 +3331,24 @@ TEST (node, dependency_graph) .from (*key3_receive) .previous (key3_receive->hash ()) .link (node.ledger.epoch_link (nano::epoch::epoch_1)) - .balance (key3_receive->balance ()) + .balance (key3_receive->balance_field ().value ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (key3_receive->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*gen_send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key1_open).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key1_send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*gen_receive).code); - ASSERT_EQ (nano::process_result::progress, node.process (*gen_send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key2_open).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key2_send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key3_open).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key2_send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key1_receive).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key1_send2).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key3_receive).code); - ASSERT_EQ (nano::process_result::progress, node.process (*key3_epoch).code); + ASSERT_EQ (nano::block_status::progress, node.process (gen_send1)); + ASSERT_EQ (nano::block_status::progress, node.process (key1_open)); + ASSERT_EQ (nano::block_status::progress, node.process (key1_send1)); + ASSERT_EQ (nano::block_status::progress, node.process (gen_receive)); + ASSERT_EQ (nano::block_status::progress, node.process (gen_send2)); + ASSERT_EQ (nano::block_status::progress, node.process (key2_open)); + ASSERT_EQ (nano::block_status::progress, node.process (key2_send1)); + ASSERT_EQ (nano::block_status::progress, node.process (key3_open)); + ASSERT_EQ (nano::block_status::progress, node.process (key2_send2)); + ASSERT_EQ (nano::block_status::progress, node.process (key1_receive)); + ASSERT_EQ (nano::block_status::progress, node.process (key1_send2)); + ASSERT_EQ (nano::block_status::progress, node.process (key3_receive)); + ASSERT_EQ (nano::block_status::progress, node.process (key3_epoch)); ASSERT_TRUE (node.active.empty ()); // Hash -> Ancestors @@ -3801,7 +3403,7 @@ TEST (node, dependency_graph) TEST (node, dependency_graph_frontier) { nano::test::system system; - nano::node_config config (system.get_available_port (), system.logging); + nano::node_config config (system.get_available_port ()); config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node1 = *system.add_node (config); config.peering_port = system.get_available_port (); @@ -3820,7 +3422,7 @@ TEST (node, dependency_graph_frontier) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); // Receive from genesis auto key1_open = builder.make_block () .account (key1.pub) @@ -3855,7 +3457,7 @@ TEST (node, dependency_graph_frontier) .from (*gen_receive) .previous (gen_receive->hash ()) .link (key2.pub) - .balance (gen_receive->balance ().number () - 2) + .balance (gen_receive->balance_field ().value ().number () - 2) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (gen_receive->hash ())) .build (); @@ -3894,7 +3496,7 @@ TEST (node, dependency_graph_frontier) .from (*key2_send1) .previous (key2_send1->hash ()) .link (key1.pub) - .balance (key2_send1->balance ().number () - 1) + .balance (key2_send1->balance_field ().value ().number () - 1) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2_send1->hash ())) .build (); @@ -3903,7 +3505,7 @@ TEST (node, dependency_graph_frontier) .from (*key1_send1) .previous (key1_send1->hash ()) .link (key2_send2->hash ()) - .balance (key1_send1->balance ().number () + 1) + .balance (key1_send1->balance_field ().value ().number () + 1) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_send1->hash ())) .build (); @@ -3912,7 +3514,7 @@ TEST (node, dependency_graph_frontier) .from (*key1_receive) .previous (key1_receive->hash ()) .link (key3.pub) - .balance (key1_receive->balance ().number () - 1) + .balance (key1_receive->balance_field ().value ().number () - 1) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_receive->hash ())) .build (); @@ -3921,7 +3523,7 @@ TEST (node, dependency_graph_frontier) .from (*key3_open) .previous (key3_open->hash ()) .link (key1_send2->hash ()) - .balance (key3_open->balance ().number () + 1) + .balance (key3_open->balance_field ().value ().number () + 1) .sign (key3.prv, key3.pub) .work (*system.work.generate (key3_open->hash ())) .build (); @@ -3930,7 +3532,7 @@ TEST (node, dependency_graph_frontier) .from (*key3_receive) .previous (key3_receive->hash ()) .link (node1.ledger.epoch_link (nano::epoch::epoch_1)) - .balance (key3_receive->balance ()) + .balance (key3_receive->balance_field ().value ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (key3_receive->hash ())) .build (); @@ -3938,19 +3540,19 @@ TEST (node, dependency_graph_frontier) for (auto const & node : system.nodes) { auto transaction (node->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *gen_send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key1_open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key1_send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *gen_receive).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *gen_send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key2_open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key2_send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key3_open).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key2_send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key1_receive).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key1_send2).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key3_receive).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *key3_epoch).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, gen_send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key1_open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key1_send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, gen_receive)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, gen_send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key2_open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key2_send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key3_open)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key2_send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key1_receive)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key1_send2)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key3_receive)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, key3_epoch)); } // node1 can vote, but only on the first block @@ -3968,9 +3570,9 @@ namespace nano TEST (node, deferred_dependent_elections) { nano::test::system system; - nano::node_config node_config_1{ system.get_available_port (), system.logging }; + nano::node_config node_config_1{ system.get_available_port () }; node_config_1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - nano::node_config node_config_2{ system.get_available_port (), system.logging }; + nano::node_config node_config_2{ system.get_available_port () }; node_config_2.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; nano::node_flags flags; flags.disable_request_loop = true; @@ -3987,7 +3589,7 @@ TEST (node, deferred_dependent_elections) .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto open = builder.make_block () .account (key.pub) .previous (0) @@ -3996,15 +3598,15 @@ TEST (node, deferred_dependent_elections) .balance (1) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); auto send2 = builder.make_block () .from (*send1) .previous (send1->hash ()) - .balance (send1->balance ().number () - 1) + .balance (send1->balance_field ().value ().number () - 1) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); auto receive = builder.make_block () .from (*open) .previous (open->hash ()) @@ -4012,12 +3614,12 @@ TEST (node, deferred_dependent_elections) .balance (2) .sign (key.prv, key.pub) .work (*system.work.generate (open->hash ())) - .build_shared (); + .build (); auto fork = builder.make_block () .from (*receive) .representative (nano::dev::genesis_key.pub) // was key.pub .sign (key.prv, key.pub) - .build_shared (); + .build (); nano::test::process (node, { send1 }); auto election_send1 = nano::test::start_election (system, node, send1->hash ()); @@ -4064,7 +3666,7 @@ TEST (node, deferred_dependent_elections) ASSERT_NE (nullptr, election_open); // Confirm one of the dependents of the receive but not the other, to ensure both have to be confirmed to start an election on processing - ASSERT_EQ (nano::process_result::progress, node.process (*receive).code); + ASSERT_EQ (nano::block_status::progress, node.process (receive)); ASSERT_FALSE (node.active.active (receive->qualified_root ())); election_open->force_confirm (); ASSERT_TIMELY (5s, node.block_confirmed (open->hash ())); @@ -4077,7 +3679,7 @@ TEST (node, deferred_dependent_elections) ASSERT_NEVER (0.5s, node.active.active (receive->qualified_root ())); // Processing a fork will also not start an election - ASSERT_EQ (nano::process_result::fork, node.process (*fork).code); + ASSERT_EQ (nano::block_status::fork, node.process (fork)); node.process_local (fork); ASSERT_NEVER (0.5s, node.active.active (receive->qualified_root ())); @@ -4088,52 +3690,13 @@ TEST (node, deferred_dependent_elections) } } -// This test checks that if a block is in the recently_confirmed list then the repcrawler will not send a request for it. -// The behaviour of this test previously was the opposite, that the repcrawler eventually send out such a block and deleted the block -// from the recently confirmed list to try to make ammends for sending it, which is bad behaviour. -// In the long term, we should have a better way to check for reps and this test should become redundant -TEST (rep_crawler, recently_confirmed) -{ - nano::test::system system (1); - auto & node1 (*system.nodes[0]); - ASSERT_EQ (1, node1.ledger.cache.block_count); - auto const block = nano::dev::genesis; - node1.active.recently_confirmed.put (block->qualified_root (), block->hash ()); - auto & node2 (*system.add_node ()); - system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); - auto channel = node1.network.find_node_id (node2.get_node_id ()); - ASSERT_NE (nullptr, channel); - node1.rep_crawler.query (channel); // this query should be dropped due to the recently_confirmed entry - ASSERT_ALWAYS_EQ (0.5s, node1.rep_crawler.representative_count (), 0); -} - -namespace nano -{ -TEST (rep_crawler, local) -{ - nano::test::system system; - nano::node_flags flags; - flags.disable_rep_crawler = true; - auto & node = *system.add_node (flags); - auto loopback = std::make_shared (node, node); - auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); - { - nano::lock_guard guard{ node.rep_crawler.probable_reps_mutex }; - node.rep_crawler.active.insert (nano::dev::genesis->hash ()); - node.rep_crawler.responses.emplace_back (loopback, vote); - } - node.rep_crawler.validate (); - ASSERT_EQ (0, node.rep_crawler.representative_count ()); -} -} - // Test that a node configured with `enable_pruning` and `max_pruning_age = 1s` will automatically // prune old confirmed blocks without explicitly saying `node.ledger_pruning` in the unit test TEST (node, pruning_automatic) { nano::test::system system{}; - nano::node_config node_config{ system.get_available_port (), system.logging }; + nano::node_config node_config{ system.get_available_port () }; // TODO: remove after allowing pruned voting node_config.enable_voting = false; node_config.max_pruning_age = std::chrono::seconds (1); @@ -4152,7 +3715,7 @@ TEST (node, pruning_automatic) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send1); latest_hash = send1->hash (); @@ -4162,7 +3725,7 @@ TEST (node, pruning_automatic) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send2); ASSERT_TIMELY (5s, node1.block (send2->hash ()) != nullptr); @@ -4179,16 +3742,14 @@ TEST (node, pruning_automatic) ASSERT_EQ (1, node1.ledger.cache.pruned_count); ASSERT_EQ (3, node1.ledger.cache.block_count); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (nano::dev::genesis->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_TRUE (nano::test::block_or_pruned_all_exists (node1, { nano::dev::genesis, send1, send2 })); } TEST (node, pruning_age) { nano::test::system system{}; - nano::node_config node_config{ system.get_available_port (), system.logging }; + nano::node_config node_config{ system.get_available_port () }; // TODO: remove after allowing pruned voting node_config.enable_voting = false; @@ -4206,7 +3767,7 @@ TEST (node, pruning_age) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send1); latest_hash = send1->hash (); @@ -4216,7 +3777,7 @@ TEST (node, pruning_age) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send2); // Force-confirm both blocks @@ -4230,19 +3791,17 @@ TEST (node, pruning_age) ASSERT_EQ (3, node1.ledger.cache.block_count); // Pruning with default age 1 day - node1.ledger_pruning (1, true, false); + node1.ledger_pruning (1, true); ASSERT_EQ (0, node1.ledger.cache.pruned_count); ASSERT_EQ (3, node1.ledger.cache.block_count); // Pruning with max age 0 node1.config.max_pruning_age = std::chrono::seconds{ 0 }; - node1.ledger_pruning (1, true, false); + node1.ledger_pruning (1, true); ASSERT_EQ (1, node1.ledger.cache.pruned_count); ASSERT_EQ (3, node1.ledger.cache.block_count); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (nano::dev::genesis->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_TRUE (nano::test::block_or_pruned_all_exists (node1, { nano::dev::genesis, send1, send2 })); } // Test that a node configured with `enable_pruning` will @@ -4251,7 +3810,7 @@ TEST (node, pruning_depth) { nano::test::system system{}; - nano::node_config node_config{ system.get_available_port (), system.logging }; + nano::node_config node_config{ system.get_available_port () }; // TODO: remove after allowing pruned voting node_config.enable_voting = false; @@ -4269,7 +3828,7 @@ TEST (node, pruning_depth) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send1); latest_hash = send1->hash (); @@ -4279,7 +3838,7 @@ TEST (node, pruning_depth) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_hash)) - .build_shared (); + .build (); node1.process_active (send2); // Force-confirm both blocks @@ -4293,44 +3852,42 @@ TEST (node, pruning_depth) ASSERT_EQ (3, node1.ledger.cache.block_count); // Pruning with default depth (unlimited) - node1.ledger_pruning (1, true, false); + node1.ledger_pruning (1, true); ASSERT_EQ (0, node1.ledger.cache.pruned_count); ASSERT_EQ (3, node1.ledger.cache.block_count); // Pruning with max depth 1 node1.config.max_pruning_depth = 1; - node1.ledger_pruning (1, true, false); + node1.ledger_pruning (1, true); ASSERT_EQ (1, node1.ledger.cache.pruned_count); ASSERT_EQ (3, node1.ledger.cache.block_count); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (nano::dev::genesis->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send2->hash ())); + ASSERT_TRUE (nano::test::block_or_pruned_all_exists (node1, { nano::dev::genesis, send1, send2 })); } TEST (node_config, node_id_private_key_persistence) { - nano::logger_mt logger; + nano::test::system system; // create the directory and the file auto path = nano::unique_path (); - ASSERT_TRUE (std::filesystem::create_directories (path)); + ASSERT_TRUE (std::filesystem::exists (path)); auto priv_key_filename = path / "node_id_private.key"; // check that the key generated is random when the key does not exist - nano::keypair kp1 = nano::load_or_create_node_id (path, logger); + nano::keypair kp1 = nano::load_or_create_node_id (path); std::filesystem::remove (priv_key_filename); - nano::keypair kp2 = nano::load_or_create_node_id (path, logger); + nano::keypair kp2 = nano::load_or_create_node_id (path); ASSERT_NE (kp1.prv, kp2.prv); // check that the key persists - nano::keypair kp3 = nano::load_or_create_node_id (path, logger); + nano::keypair kp3 = nano::load_or_create_node_id (path); ASSERT_EQ (kp2.prv, kp3.prv); // write the key file manually and check that right key is loaded std::ofstream ofs (priv_key_filename.string (), std::ofstream::out | std::ofstream::trunc); ofs << "3F28D035B8AA75EA53DF753BFD065CF6138E742971B2C99B84FD8FE328FED2D9" << std::flush; ofs.close (); - nano::keypair kp4 = nano::load_or_create_node_id (path, logger); + nano::keypair kp4 = nano::load_or_create_node_id (path); ASSERT_EQ (kp4.prv, nano::keypair ("3F28D035B8AA75EA53DF753BFD065CF6138E742971B2C99B84FD8FE328FED2D9").prv); } diff --git a/nano/core_test/object_stream.cpp b/nano/core_test/object_stream.cpp new file mode 100644 index 0000000000..11f14922ff --- /dev/null +++ b/nano/core_test/object_stream.cpp @@ -0,0 +1,591 @@ +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace +{ +std::string trim (std::string_view str) +{ + return boost::trim_copy (std::string{ str }); +} +} + +TEST (object_stream, primitive_string) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("field_name_1", "field_value"); + + auto expected = R"(field_name_1: "field_value")"; + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_string_view) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("field_name_1", std::string_view{ "field_value" }); + + auto expected = R"(field_name_1: "field_value")"; + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_char) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("field_name_1", 'a'); + + auto expected = R"(field_name_1: "a")"; + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_bool) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("bool_field_1", true); + obs.write ("bool_field_2", false); + + auto expected = trim (R"( +bool_field_1: true, +bool_field_2: false +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_int) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("int_field_1", 1234); + obs.write ("int_field_2", -1234); + obs.write ("int_field_3", std::numeric_limits::max ()); + obs.write ("int_field_4", std::numeric_limits::min ()); + + auto expected = trim (R"( +int_field_1: 1234, +int_field_2: -1234, +int_field_3: 2147483647, +int_field_4: -2147483648 +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_uint) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("uint_field_1", static_cast (1234)); + obs.write ("uint_field_2", static_cast (-1234)); + obs.write ("uint_field_3", std::numeric_limits::max ()); + obs.write ("uint_field_4", std::numeric_limits::min ()); + + auto expected = trim (R"( +uint_field_1: 1234, +uint_field_2: 4294966062, +uint_field_3: 4294967295, +uint_field_4: 0 +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_uint64) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("uint64_field_1", static_cast (1234)); + obs.write ("uint64_field_2", static_cast (-1234)); + obs.write ("uint64_field_3", std::numeric_limits::max ()); + obs.write ("uint64_field_4", std::numeric_limits::min ()); + + auto expected = trim (R"( +uint64_field_1: 1234, +uint64_field_2: 18446744073709550382, +uint64_field_3: 18446744073709551615, +uint64_field_4: 0 +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_int8) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("int8_field_1", static_cast (123)); + + auto expected = R"(int8_field_1: 123)"; + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_uint8) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("uint8_field_1", static_cast (123)); + + auto expected = R"(uint8_field_1: 123)"; + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_float) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("float_field_1", 1234.5678f); + obs.write ("float_field_2", -1234.5678f); + obs.write ("float_field_3", std::numeric_limits::max ()); + obs.write ("float_field_4", std::numeric_limits::min ()); + obs.write ("float_field_5", std::numeric_limits::lowest ()); + + auto expected = trim (R"( +float_field_1: 1234.57, +float_field_2: -1234.57, +float_field_3: 340282346638528859811704183484516925440.00, +float_field_4: 0.00, +float_field_5: -340282346638528859811704183484516925440.00 +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, primitive_double) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("double_field_1", 1234.5678f); + obs.write ("double_field_2", -1234.5678f); + obs.write ("double_field_3", std::numeric_limits::max ()); + obs.write ("double_field_4", std::numeric_limits::min ()); + obs.write ("double_field_5", std::numeric_limits::lowest ()); + + auto expected = trim (R"( +double_field_1: 1234.57, +double_field_2: -1234.57, +double_field_3: 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00, +double_field_4: 0.00, +double_field_5: -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00 +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, object_writer_basic) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("object_field", [] (nano::object_stream & obs) { + obs.write ("field1", "value1"); + obs.write ("field2", "value2"); + obs.write ("field3", true); + obs.write ("field4", 1234); + }); + + auto expected = trim (R"( +object_field: { + field1: "value1", + field2: "value2", + field3: true, + field4: 1234 +} +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, object_writer_nested) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("object_field", [] (nano::object_stream & obs) { + obs.write ("field1", "value1"); + + obs.write ("nested_object", [] (nano::object_stream & obs) { + obs.write ("nested_field1", "nested_value1"); + obs.write ("nested_field2", false); + obs.write ("nested_field3", -1234); + }); + + obs.write ("field2", "value2"); + obs.write ("field3", true); + obs.write ("field4", 1234); + }); + + auto expected = trim (R"( +object_field: { + field1: "value1", + nested_object: { + nested_field1: "nested_value1", + nested_field2: false, + nested_field3: -1234 + }, + field2: "value2", + field3: true, + field4: 1234 +} +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, array_writer_basic) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + obs.write ("array_field", [] (nano::array_stream & ars) { + ars.write (std::views::iota (0, 3)); + }); + + auto expected = trim (R"( +array_field: [ + 0, + 1, + 2 +] +)"); + + ASSERT_EQ (ss.str (), expected); +} + +namespace +{ +class object_basic +{ +public: + nano::uint256_union uint256_union_field{ 0 }; + nano::block_hash block_hash{ 0 }; + + void operator() (nano::object_stream & obs) const + { + obs.write ("uint256_union_field", uint256_union_field); + obs.write ("block_hash", block_hash); + } +}; +} + +TEST (object_stream, object_basic) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + object_basic test_object; + obs.write ("test_object", test_object); + + auto expected = trim (R"( +test_object: { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" +} +)"); + + ASSERT_EQ (ss.str (), expected); +} + +TEST (object_stream, array_writer_objects) +{ + std::stringstream ss; + + std::vector objects; + objects.push_back ({ .block_hash = 0 }); + objects.push_back ({ .block_hash = 1 }); + objects.push_back ({ .block_hash = 2 }); + + nano::object_stream obs{ ss }; + obs.write ("array_field", [&objects] (nano::array_stream & ars) { + ars.write (objects); + }); + + auto expected = trim (R"( +array_field: [ + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000002" + } +] +)"); + + ASSERT_EQ (ss.str (), expected); +} + +namespace +{ +class object_array_basic +{ +public: + std::vector values{ 1, 2, 3 }; + + void operator() (nano::array_stream & ars) const + { + ars.write (values); + } +}; +} + +TEST (object_stream, object_array_basic) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + object_array_basic test_object; + obs.write ("test_object_array", test_object); + + auto expected = trim (R"( +test_object_array: [ + 1, + 2, + 3 +] +)"); + + ASSERT_EQ (ss.str (), expected); +} + +namespace +{ +class object_nested +{ +public: + nano::uint256_union uint256_union_field{ 0 }; + nano::block_hash block_hash{ 0 }; + + object_basic nested_object; + object_array_basic nested_array_object; + + void operator() (nano::object_stream & obs) const + { + obs.write ("uint256_union_field", uint256_union_field); + obs.write ("block_hash", block_hash); + obs.write ("nested_object", nested_object); + obs.write ("nested_array_object", nested_array_object); + } +}; +} + +TEST (object_stream, object_nested) +{ + std::stringstream ss; + + nano::object_stream obs{ ss }; + object_nested test_object; + obs.write ("test_object", test_object); + + auto expected = trim (R"( +test_object: { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000", + nested_object: { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" + }, + nested_array_object: [ + 1, + 2, + 3 + ] +} +)"); + + ASSERT_EQ (ss.str (), expected); +} + +namespace nano +{ +using builtin_array_with_pair = std::vector>; + +void stream_as (std::pair const & entry, nano::object_stream & obs) +{ + auto const & [hash, value] = entry; + obs.write ("hash", hash); + obs.write ("value", value); +} +} + +TEST (object_stream, builtin_array) +{ + using namespace nano; + + std::stringstream ss; + + builtin_array_with_pair array; + array.push_back ({ nano::block_hash{ 1 }, 1 }); + array.push_back ({ nano::block_hash{ 2 }, 2 }); + array.push_back ({ nano::block_hash{ 3 }, 3 }); + + nano::object_stream obs{ ss }; + obs.write_range ("array_field", array); + + auto expected = trim (R"( +array_field: [ + { + hash: "0000000000000000000000000000000000000000000000000000000000000001", + value: 1 + }, + { + hash: "0000000000000000000000000000000000000000000000000000000000000002", + value: 2 + }, + { + hash: "0000000000000000000000000000000000000000000000000000000000000003", + value: 3 + } +] +)"); + + ASSERT_EQ (ss.str (), expected); +} + +namespace +{ +class streamable_object +{ +public: + nano::uint256_union uint256_union_field{ 0 }; + nano::block_hash block_hash{ 0 }; + + void operator() (nano::object_stream & obs) const + { + obs.write ("uint256_union_field", uint256_union_field); + obs.write ("block_hash", block_hash); + } +}; +} + +TEST (object_stream, ostream_adapter) +{ + using namespace nano::object_stream_adapters; + + std::stringstream ss1, ss2; + + streamable_object test_object; + ss1 << test_object; // Using automatic ostream adapter (in `nano::ostream_operators`) + ss2 << nano::streamed (test_object); // Using explicit ostream adapter + + auto expected = trim (R"( +{ + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" +} +)"); + + ASSERT_EQ (ss1.str (), expected); + ASSERT_EQ (ss2.str (), expected); +} + +TEST (object_stream, fmt_adapter) +{ + streamable_object test_object; + auto str1 = fmt::format ("{}", test_object); // Using automatic fmt adapter + auto str2 = fmt::format ("{}", nano::streamed (test_object)); // Using explicit fmt adapter + + auto expected = trim (R"( +{ + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" +} +)"); + + ASSERT_EQ (str1, expected); + ASSERT_EQ (str2, expected); +} + +TEST (object_stream, to_string) +{ + using namespace nano::object_stream_adapters; + + streamable_object test_object; + auto str = to_string (test_object); // Using automatic to_string adapter + + auto expected = trim (R"( +{ + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000000", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" +} +)"); + + ASSERT_EQ (str, expected); +} + +TEST (object_stream, to_json) +{ + using namespace nano::object_stream_adapters; + + streamable_object test_object; + auto str = to_json (test_object); // Using automatic to_string adapter + + auto expected = trim (R"( +{"uint256_union_field":"0000000000000000000000000000000000000000000000000000000000000000","block_hash":"0000000000000000000000000000000000000000000000000000000000000000"} +)"); + + ASSERT_EQ (str, expected); +} + +TEST (object_stream, print_range) +{ + std::deque objects; + objects.push_back ({ 1 }); + objects.push_back ({ 2 }); + objects.push_back ({ 3 }); + + std::stringstream ss1, ss2; + ss1 << nano::streamed_range (objects); + ss2 << fmt::format ("{}", nano::streamed_range (objects)); + + auto expected = trim (R"( +[ + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000001", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000002", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000003", + block_hash: "0000000000000000000000000000000000000000000000000000000000000000" + } +] +)"); + + ASSERT_EQ (ss1.str (), expected); + ASSERT_EQ (ss2.str (), expected); +} diff --git a/nano/core_test/optimistic_scheduler.cpp b/nano/core_test/optimistic_scheduler.cpp index 0f03c04fce..789eb66b3c 100644 --- a/nano/core_test/optimistic_scheduler.cpp +++ b/nano/core_test/optimistic_scheduler.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/core_test/processor_service.cpp b/nano/core_test/processor_service.cpp index 42893a97d0..959495d1db 100644 --- a/nano/core_test/processor_service.cpp +++ b/nano/core_test/processor_service.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -10,7 +12,7 @@ TEST (processor_service, bad_send_signature) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::stats stats; @@ -31,12 +33,12 @@ TEST (processor_service, bad_send_signature) .work (*pool.generate (info1->head)) .build (); send->signature.bytes[32] ^= 0x1; - ASSERT_EQ (nano::process_result::bad_signature, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::bad_signature, ledger.process (transaction, send)); } TEST (processor_service, bad_receive_signature) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::stats stats; @@ -56,7 +58,7 @@ TEST (processor_service, bad_receive_signature) .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (info2); auto receive = builder @@ -67,5 +69,5 @@ TEST (processor_service, bad_receive_signature) .work (*pool.generate (hash1)) .build (); receive->signature.bytes[32] ^= 0x1; - ASSERT_EQ (nano::process_result::bad_signature, ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::bad_signature, ledger.process (transaction, receive)); } diff --git a/nano/core_test/rep_crawler.cpp b/nano/core_test/rep_crawler.cpp new file mode 100644 index 0000000000..06d16b895d --- /dev/null +++ b/nano/core_test/rep_crawler.cpp @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace std::chrono_literals; + +// Test that nodes can track nodes that have rep weight for priority broadcasting +TEST (rep_crawler, rep_list) +{ + nano::test::system system; + auto & node1 = *system.add_node (); + auto & node2 = *system.add_node (); + ASSERT_EQ (0, node2.rep_crawler.representative_count ()); + // Node #1 has a rep + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + ASSERT_TIMELY_EQ (5s, node2.rep_crawler.representative_count (), 1); + auto reps = node2.rep_crawler.representatives (); + ASSERT_EQ (1, reps.size ()); + ASSERT_EQ (nano::dev::genesis_key.pub, reps[0].account); +} + +TEST (rep_crawler, rep_weight) +{ + nano::test::system system; + auto & node = *system.add_node (); + auto & node1 = *system.add_node (); + auto & node2 = *system.add_node (); + auto & node3 = *system.add_node (); + nano::keypair keypair1; + nano::keypair keypair2; + nano::block_builder builder; + auto const amount_pr = node.minimum_principal_weight () + 100; + auto const amount_not_pr = node.minimum_principal_weight () - 100; + std::shared_ptr block1 = builder + .state () + .account (nano::dev::genesis_key.pub) + .previous (nano::dev::genesis->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - amount_not_pr) + .link (keypair1.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + std::shared_ptr block2 = builder + .state () + .account (keypair1.pub) + .previous (0) + .representative (keypair1.pub) + .balance (amount_not_pr) + .link (block1->hash ()) + .sign (keypair1.prv, keypair1.pub) + .work (*system.work.generate (keypair1.pub)) + .build (); + std::shared_ptr block3 = builder + .state () + .account (nano::dev::genesis_key.pub) + .previous (block1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - amount_not_pr - amount_pr) + .link (keypair2.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (block1->hash ())) + .build (); + std::shared_ptr block4 = builder + .state () + .account (keypair2.pub) + .previous (0) + .representative (keypair2.pub) + .balance (amount_pr) + .link (block3->hash ()) + .sign (keypair2.prv, keypair2.pub) + .work (*system.work.generate (keypair2.pub)) + .build (); + ASSERT_TRUE (nano::test::process (node, { block1, block2, block3, block4 })); + ASSERT_TRUE (nano::test::process (node1, { block1, block2, block3, block4 })); + ASSERT_TRUE (nano::test::process (node2, { block1, block2, block3, block4 })); + ASSERT_TRUE (nano::test::process (node3, { block1, block2, block3, block4 })); + ASSERT_TRUE (node.rep_crawler.representatives (1).empty ()); + std::shared_ptr channel1 = nano::test::establish_tcp (system, node, node1.network.endpoint ()); + ASSERT_NE (nullptr, channel1); + std::shared_ptr channel2 = nano::test::establish_tcp (system, node, node2.network.endpoint ()); + ASSERT_NE (nullptr, channel2); + std::shared_ptr channel3 = nano::test::establish_tcp (system, node, node3.network.endpoint ()); + ASSERT_NE (nullptr, channel3); + auto vote0 = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + auto vote1 = std::make_shared (keypair1.pub, keypair1.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + auto vote2 = std::make_shared (keypair2.pub, keypair2.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + node.rep_crawler.force_process (vote0, channel1); + node.rep_crawler.force_process (vote1, channel2); + node.rep_crawler.force_process (vote2, channel3); + ASSERT_TIMELY_EQ (5s, node.rep_crawler.representative_count (), 2); + // Make sure we get the rep with the most weight first + auto reps = node.rep_crawler.representatives (1); + ASSERT_EQ (1, reps.size ()); + ASSERT_EQ (node.balance (nano::dev::genesis_key.pub), node.ledger.weight (reps[0].account)); + ASSERT_EQ (nano::dev::genesis_key.pub, reps[0].account); + ASSERT_EQ (*channel1, *reps[0].channel); + ASSERT_TRUE (node.rep_crawler.is_pr (channel1)); + ASSERT_FALSE (node.rep_crawler.is_pr (channel2)); + ASSERT_TRUE (node.rep_crawler.is_pr (channel3)); +} + +// Test that rep_crawler removes unreachable reps from its search results. +// This test creates three principal representatives (rep1, rep2, genesis_rep) and +// one node for searching them (searching_node). +TEST (rep_crawler, rep_remove) +{ + nano::test::system system; + auto & searching_node = *system.add_node (); // will be used to find principal representatives + nano::keypair keys_rep1; // Principal representative 1 + nano::keypair keys_rep2; // Principal representative 2 + nano::block_builder builder; + + // Send enough nanos to Rep1 to make it a principal representative + std::shared_ptr send_to_rep1 = builder + .state () + .account (nano::dev::genesis_key.pub) + .previous (nano::dev::genesis->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 2) + .link (keys_rep1.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (nano::dev::genesis->hash ())) + .build (); + + // Receive by Rep1 + std::shared_ptr receive_rep1 = builder + .state () + .account (keys_rep1.pub) + .previous (0) + .representative (keys_rep1.pub) + .balance (searching_node.minimum_principal_weight () * 2) + .link (send_to_rep1->hash ()) + .sign (keys_rep1.prv, keys_rep1.pub) + .work (*system.work.generate (keys_rep1.pub)) + .build (); + + // Send enough nanos to Rep2 to make it a principal representative + std::shared_ptr send_to_rep2 = builder + .state () + .account (nano::dev::genesis_key.pub) + .previous (send_to_rep1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 4) + .link (keys_rep2.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (send_to_rep1->hash ())) + .build (); + + // Receive by Rep2 + std::shared_ptr receive_rep2 = builder + .state () + .account (keys_rep2.pub) + .previous (0) + .representative (keys_rep2.pub) + .balance (searching_node.minimum_principal_weight () * 2) + .link (send_to_rep2->hash ()) + .sign (keys_rep2.prv, keys_rep2.pub) + .work (*system.work.generate (keys_rep2.pub)) + .build (); + { + auto transaction = searching_node.store.tx_begin_write (); + ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, send_to_rep1)); + ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, receive_rep1)); + ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, send_to_rep2)); + ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, receive_rep2)); + } + + // Create channel for Rep1 + auto channel_rep1 (std::make_shared (searching_node)); + + // Ensure Rep1 is found by the rep_crawler after receiving a vote from it + auto vote_rep1 = std::make_shared (keys_rep1.pub, keys_rep1.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + searching_node.rep_crawler.force_process (vote_rep1, channel_rep1); + ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 1); + auto reps (searching_node.rep_crawler.representatives (1)); + ASSERT_EQ (1, reps.size ()); + ASSERT_EQ (searching_node.minimum_principal_weight () * 2, searching_node.ledger.weight (reps[0].account)); + ASSERT_EQ (keys_rep1.pub, reps[0].account); + ASSERT_EQ (*channel_rep1, *reps[0].channel); + + // When rep1 disconnects then rep1 should not be found anymore + channel_rep1->close (); + ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 0); + + // Add working node for genesis representative + auto node_genesis_rep = system.add_node (nano::node_config (system.get_available_port ())); + system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); + auto channel_genesis_rep (searching_node.network.find_node_id (node_genesis_rep->get_node_id ())); + ASSERT_NE (nullptr, channel_genesis_rep); + + // genesis_rep should be found as principal representative after receiving a vote from it + auto vote_genesis_rep = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + searching_node.rep_crawler.force_process (vote_genesis_rep, channel_genesis_rep); + ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 1); + + // Start a node for Rep2 and wait until it is connected + auto node_rep2 (std::make_shared (system.io_ctx, nano::unique_path (), nano::node_config (system.get_available_port ()), system.work)); + node_rep2->start (); + searching_node.network.tcp_channels.start_tcp (node_rep2->network.endpoint ()); + std::shared_ptr channel_rep2; + ASSERT_TIMELY (10s, (channel_rep2 = searching_node.network.tcp_channels.find_node_id (node_rep2->get_node_id ())) != nullptr); + + // Rep2 should be found as a principal representative after receiving a vote from it + auto vote_rep2 = std::make_shared (keys_rep2.pub, keys_rep2.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + searching_node.rep_crawler.force_process (vote_rep2, channel_rep2); + ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 2); + + // When Rep2 is stopped, it should not be found as principal representative anymore + node_rep2->stop (); + ASSERT_TIMELY_EQ (10s, searching_node.rep_crawler.representative_count (), 1); + + // Now only genesisRep should be found: + reps = searching_node.rep_crawler.representatives (1); + ASSERT_EQ (nano::dev::genesis_key.pub, reps[0].account); + ASSERT_TIMELY_EQ (5s, searching_node.network.size (), 1); + auto list (searching_node.network.list (1)); + ASSERT_EQ (node_genesis_rep->network.endpoint (), list[0]->get_endpoint ()); +} + +TEST (rep_crawler, rep_connection_close) +{ + nano::test::system system; + auto & node1 = *system.add_node (); + auto & node2 = *system.add_node (); + // Add working representative (node 2) + system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); + ASSERT_TIMELY_EQ (10s, node1.rep_crawler.representative_count (), 1); + node2.stop (); + // Remove representative with closed channel + ASSERT_TIMELY_EQ (10s, node1.rep_crawler.representative_count (), 0); +} + +// This test checks that if a block is in the recently_confirmed list then the repcrawler will not send a request for it. +// The behaviour of this test previously was the opposite, that the repcrawler eventually send out such a block and deleted the block +// from the recently confirmed list to try to make ammends for sending it, which is bad behaviour. +// In the long term, we should have a better way to check for reps and this test should become redundant +TEST (rep_crawler, recently_confirmed) +{ + nano::test::system system (1); + auto & node1 (*system.nodes[0]); + ASSERT_EQ (1, node1.ledger.cache.block_count); + auto const block = nano::dev::genesis; + node1.active.recently_confirmed.put (block->qualified_root (), block->hash ()); + auto & node2 (*system.add_node ()); + system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv); + auto channel = node1.network.find_node_id (node2.get_node_id ()); + ASSERT_NE (nullptr, channel); + node1.rep_crawler.query (channel); // this query should be dropped due to the recently_confirmed entry + ASSERT_ALWAYS_EQ (0.5s, node1.rep_crawler.representative_count (), 0); +} + +// Votes from local channels should be ignored +TEST (rep_crawler, ignore_local) +{ + nano::test::system system; + nano::node_flags flags; + auto & node = *system.add_node (flags); + auto loopback = std::make_shared (node, node); + auto vote = std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () }); + node.rep_crawler.force_process (vote, loopback); + ASSERT_ALWAYS_EQ (0.5s, node.rep_crawler.representative_count (), 0); +} + +// Test that nodes can track PRs when multiple PRs are inside one node +TEST (rep_crawler, two_reps_one_node) +{ + nano::test::system system; + auto & node1 = *system.add_node (); + auto & node2 = *system.add_node (); + + // create a second PR account + nano::keypair second_rep = nano::test::setup_rep (system, node1, node1.balance (nano::dev::genesis_key.pub) / 10); + ASSERT_EQ (0, node2.rep_crawler.representative_count ()); + + // enable the two PRs in node1 + system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); + system.wallet (0)->insert_adhoc (second_rep.prv); + + ASSERT_TIMELY_EQ (5s, node2.rep_crawler.representative_count (), 2); + auto reps = node2.rep_crawler.representatives (); + ASSERT_EQ (2, reps.size ()); + + // check that the reps are correct + ASSERT_TRUE (nano::dev::genesis_key.pub == reps[0].account || nano::dev::genesis_key.pub == reps[1].account); + ASSERT_TRUE (second_rep.pub == reps[0].account || second_rep.pub == reps[1].account); +} diff --git a/nano/core_test/request_aggregator.cpp b/nano/core_test/request_aggregator.cpp index 9eb4a73159..7b1913f411 100644 --- a/nano/core_test/request_aggregator.cpp +++ b/nano/core_test/request_aggregator.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include #include @@ -26,7 +28,7 @@ TEST (request_aggregator, one) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); auto client = std::make_shared (node); @@ -36,7 +38,7 @@ TEST (request_aggregator, one) ASSERT_TIMELY (3s, node.aggregator.empty ()); // Not yet in the ledger ASSERT_TIMELY_EQ (3s, 1, node.stats.count (nano::stat::type::requests, nano::stat::detail::requests_unknown)); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); node.aggregator.add (dummy_channel, request); ASSERT_EQ (1, node.aggregator.size ()); // In the ledger but no vote generated yet @@ -72,8 +74,8 @@ TEST (request_aggregator, one_update) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); node.confirmation_height_processor.add (send1); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = nano::state_block_builder () @@ -84,8 +86,8 @@ TEST (request_aggregator, one_update) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send2)); auto receive1 = nano::state_block_builder () .account (key1.pub) .previous (0) @@ -94,8 +96,8 @@ TEST (request_aggregator, one_update) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node.work_generate_blocking (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), receive1)); std::vector> request; request.emplace_back (send2->hash (), send2->root ()); auto client = std::make_shared (node); @@ -138,8 +140,8 @@ TEST (request_aggregator, two) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); node.confirmation_height_processor.add (send1); ASSERT_TIMELY (5s, node.ledger.block_confirmed (node.store.tx_begin_read (), send1->hash ())); auto send2 = builder.make_block () @@ -150,7 +152,7 @@ TEST (request_aggregator, two) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); auto receive1 = builder.make_block () .account (key1.pub) .previous (0) @@ -159,9 +161,9 @@ TEST (request_aggregator, two) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*node.work_generate_blocking (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send2).code); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *receive1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send2)); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), receive1)); std::vector> request; request.emplace_back (send2->hash (), send2->root ()); request.emplace_back (receive1->hash (), receive1->root ()); @@ -215,10 +217,10 @@ TEST (request_aggregator, two_endpoints) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (node1.store.tx_begin_write (), *send1).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (node1.store.tx_begin_write (), send1)); auto dummy_channel1 = std::make_shared (node1, node1); auto dummy_channel2 = std::make_shared (node2, node2); ASSERT_NE (nano::transport::map_endpoint_to_v6 (dummy_channel1->get_endpoint ()), nano::transport::map_endpoint_to_v6 (dummy_channel2->get_endpoint ())); @@ -279,7 +281,7 @@ TEST (request_aggregator, split) .build ()); auto const & block = blocks.back (); previous = block->hash (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *block).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), block)); request.emplace_back (block->hash (), block->root ()); } // Confirm all blocks @@ -324,8 +326,8 @@ TEST (request_aggregator, channel_lifetime) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); { @@ -355,8 +357,8 @@ TEST (request_aggregator, channel_update) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); std::weak_ptr channel1_w; @@ -395,8 +397,8 @@ TEST (request_aggregator, channel_max_queue) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); auto client = std::make_shared (node); @@ -423,8 +425,8 @@ TEST (request_aggregator, unique) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node.work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); std::vector> request; request.emplace_back (send1->hash (), send1->root ()); auto client = std::make_shared (node); @@ -456,16 +458,16 @@ TEST (request_aggregator, cannot_vote) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .from (*send1) .previous (send1->hash ()) - .balance (send1->balance ().number () - 1) + .balance (send1->balance_field ().value ().number () - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node.process (*send2).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.process (send1)); + ASSERT_EQ (nano::block_status::progress, node.process (send2)); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); ASSERT_FALSE (node.ledger.dependents_confirmed (node.store.tx_begin_read (), *send2)); diff --git a/nano/core_test/scheduler_buckets.cpp b/nano/core_test/scheduler_buckets.cpp index 0a9c6adfba..43912e29b9 100644 --- a/nano/core_test/scheduler_buckets.cpp +++ b/nano/core_test/scheduler_buckets.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -42,7 +43,7 @@ std::shared_ptr & blockzero () .link (0) .sign (keyzero ().prv, keyzero ().pub) .work (0) - .build_shared (); + .build (); return result; } std::shared_ptr & block0 () @@ -57,7 +58,7 @@ std::shared_ptr & block0 () .link (0) .sign (key0 ().prv, key0 ().pub) .work (0) - .build_shared (); + .build (); return result; } std::shared_ptr & block1 () @@ -72,7 +73,7 @@ std::shared_ptr & block1 () .link (0) .sign (key1 ().prv, key1 ().pub) .work (0) - .build_shared (); + .build (); return result; } std::shared_ptr & block2 () @@ -87,7 +88,7 @@ std::shared_ptr & block2 () .link (0) .sign (key2 ().prv, key2 ().pub) .work (0) - .build_shared (); + .build (); return result; } std::shared_ptr & block3 () @@ -102,7 +103,7 @@ std::shared_ptr & block3 () .link (0) .sign (key3 ().prv, key3 ().pub) .work (0) - .build_shared (); + .build (); return result; } diff --git a/nano/core_test/socket.cpp b/nano/core_test/socket.cpp index 02a19e9c56..eaa31f761b 100644 --- a/nano/core_test/socket.cpp +++ b/nano/core_test/socket.cpp @@ -115,7 +115,7 @@ TEST (socket, max_connections_per_ip) auto server_port = system.get_available_port (); const auto max_ip_connections = node->network_params.network.max_peers_per_ip; - ASSERT_TRUE (max_ip_connections >= 1); + ASSERT_GE (max_ip_connections, 1); const auto max_global_connections = 1000; @@ -235,7 +235,7 @@ TEST (socket, max_connections_per_subnetwork) boost::asio::ip::tcp::endpoint listen_endpoint{ boost::asio::ip::address_v6::any (), server_port }; const auto max_subnetwork_connections = node->network_params.network.max_peers_per_subnetwork; - ASSERT_TRUE (max_subnetwork_connections >= 1); + ASSERT_GE (max_subnetwork_connections, 1); const auto max_global_connections = 1000; @@ -295,7 +295,7 @@ TEST (socket, disabled_max_peers_per_ip) auto server_port = system.get_available_port (); const auto max_ip_connections = node->network_params.network.max_peers_per_ip; - ASSERT_TRUE (max_ip_connections >= 1); + ASSERT_GE (max_ip_connections, 1); const auto max_global_connections = 1000; @@ -572,6 +572,11 @@ TEST (socket, concurrent_writes) * set timeout to one second * do a tcp connect that will block for at least a few seconds at the tcp level * check that the connect returns error and that the correct counters have been incremented + * + * NOTE: it is possible that the O/S has tried to access the IP address 10.255.254.253 before + * and has it marked in the routing table as unroutable. In that case this test case will fail. + * If this test is run repeadetly the tests fails for this reason because the connection fails + * with "No route to host" error instead of a timeout. */ TEST (socket_timeout, connect) { @@ -603,6 +608,8 @@ TEST (socket_timeout, connect) ASSERT_EQ (1, node->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_connect_error, nano::stat::dir::in)); // check that the socket was closed due to tcp_io_timeout timeout + // NOTE: this assert is not guaranteed to be always true, it is only likely that it will be true, we can also get "No route to host" + // if this test is run repeatedly or in parallel then it is guaranteed to fail due to "No route to host" instead of timeout ASSERT_EQ (1, node->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_io_timeout_drop, nano::stat::dir::out)); } diff --git a/nano/core_test/system.cpp b/nano/core_test/system.cpp index 41e7f9c841..ffd860180f 100644 --- a/nano/core_test/system.cpp +++ b/nano/core_test/system.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include #include @@ -30,7 +32,7 @@ TEST (system, system_genesis) for (auto & i : system.nodes) { auto transaction (i->store.tx_begin_read ()); - ASSERT_EQ (nano::dev::constants.genesis_amount, i->ledger.account_balance (transaction, nano::dev::genesis->account ())); + ASSERT_EQ (nano::dev::constants.genesis_amount, i->ledger.account_balance (transaction, nano::dev::genesis_key.pub)); } } @@ -41,7 +43,7 @@ TEST (system, DISABLED_generate_send_existing) nano::thread_runner runner (system.io_ctx, node1.config.io_threads); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); nano::keypair stake_preserver; - auto send_block (system.wallet (0)->send_action (nano::dev::genesis->account (), stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); + auto send_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); auto info1 = node1.ledger.account_info (node1.store.tx_begin_read (), nano::dev::genesis_key.pub); ASSERT_TRUE (info1); std::vector accounts; @@ -54,15 +56,15 @@ TEST (system, DISABLED_generate_send_existing) auto open_block = builder .open () .source (send_block->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (stake_preserver.pub) .sign (stake_preserver.prv, stake_preserver.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open_block); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *open_block).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, open_block)); } - ASSERT_GT (node1.balance (stake_preserver.pub), node1.balance (nano::dev::genesis->account ())); + ASSERT_GT (node1.balance (stake_preserver.pub), node1.balance (nano::dev::genesis_key.pub)); auto info2 = node1.ledger.account_info (node1.store.tx_begin_read (), nano::dev::genesis_key.pub); ASSERT_TRUE (info2); ASSERT_NE (info1->head, info2->head); @@ -98,22 +100,22 @@ TEST (system, DISABLED_generate_send_new) ASSERT_EQ (node1.store.account.end (), iterator1); } nano::keypair stake_preserver; - auto send_block (system.wallet (0)->send_action (nano::dev::genesis->account (), stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); + auto send_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); { auto transaction (node1.store.tx_begin_write ()); nano::block_builder builder; auto open_block = builder .open () .source (send_block->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (stake_preserver.pub) .sign (stake_preserver.prv, stake_preserver.pub) .work (0) - .build_shared (); + .build (); node1.work_generate_blocking (*open_block); - ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *open_block).code); + ASSERT_EQ (nano::block_status::progress, node1.ledger.process (transaction, open_block)); } - ASSERT_GT (node1.balance (stake_preserver.pub), node1.balance (nano::dev::genesis->account ())); + ASSERT_GT (node1.balance (stake_preserver.pub), node1.balance (nano::dev::genesis_key.pub)); std::vector accounts; accounts.push_back (nano::dev::genesis_key.pub); // This indirectly waits for online weight to stabilize, required to prevent intermittent failures diff --git a/nano/core_test/timer.cpp b/nano/core_test/timer.cpp index cf718f11bd..85b3040739 100644 --- a/nano/core_test/timer.cpp +++ b/nano/core_test/timer.cpp @@ -39,7 +39,7 @@ TEST (timer, measure_and_compare) std::this_thread::sleep_for (50ms); ASSERT_TRUE (t1.after_deadline (30ms)); ASSERT_TRUE (t1.before_deadline (500ms)); - ASSERT_LT (t1.since_start (), 200ms); + ASSERT_LT (t1.since_start (), 500ms); ASSERT_GT (t1.since_start (), 10ms); ASSERT_GE (t1.stop (), 50ms); std::this_thread::sleep_for (50ms); diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index 9d96fd367f..9e2a5cbe83 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -193,38 +193,11 @@ TEST (toml, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.work_peers, defaults.node.work_peers); ASSERT_EQ (conf.node.work_threads, defaults.node.work_threads); ASSERT_EQ (conf.node.max_queued_requests, defaults.node.max_queued_requests); + ASSERT_EQ (conf.node.request_aggregator_threads, defaults.node.request_aggregator_threads); + ASSERT_EQ (conf.node.max_unchecked_blocks, defaults.node.max_unchecked_blocks); ASSERT_EQ (conf.node.backlog_scan_batch_size, defaults.node.backlog_scan_batch_size); ASSERT_EQ (conf.node.backlog_scan_frequency, defaults.node.backlog_scan_frequency); - ASSERT_EQ (conf.node.logging.bulk_pull_logging_value, defaults.node.logging.bulk_pull_logging_value); - ASSERT_EQ (conf.node.logging.flush, defaults.node.logging.flush); - ASSERT_EQ (conf.node.logging.insufficient_work_logging_value, defaults.node.logging.insufficient_work_logging_value); - ASSERT_EQ (conf.node.logging.ledger_logging_value, defaults.node.logging.ledger_logging_value); - ASSERT_EQ (conf.node.logging.ledger_duplicate_logging_value, defaults.node.logging.ledger_duplicate_logging_value); - ASSERT_EQ (conf.node.logging.log_ipc_value, defaults.node.logging.log_ipc_value); - ASSERT_EQ (conf.node.logging.log_to_cerr_value, defaults.node.logging.log_to_cerr_value); - ASSERT_EQ (conf.node.logging.max_size, defaults.node.logging.max_size); - ASSERT_EQ (conf.node.logging.min_time_between_log_output.count (), defaults.node.logging.min_time_between_log_output.count ()); - ASSERT_EQ (conf.node.logging.network_logging_value, defaults.node.logging.network_logging_value); - ASSERT_EQ (conf.node.logging.network_keepalive_logging_value, defaults.node.logging.network_keepalive_logging_value); - ASSERT_EQ (conf.node.logging.network_message_logging_value, defaults.node.logging.network_message_logging_value); - ASSERT_EQ (conf.node.logging.network_node_id_handshake_logging_value, defaults.node.logging.network_node_id_handshake_logging_value); - ASSERT_EQ (conf.node.logging.network_packet_logging_value, defaults.node.logging.network_packet_logging_value); - ASSERT_EQ (conf.node.logging.network_publish_logging_value, defaults.node.logging.network_publish_logging_value); - ASSERT_EQ (conf.node.logging.network_timeout_logging_value, defaults.node.logging.network_timeout_logging_value); - ASSERT_EQ (conf.node.logging.node_lifetime_tracing_value, defaults.node.logging.node_lifetime_tracing_value); - ASSERT_EQ (conf.node.logging.network_telemetry_logging_value, defaults.node.logging.network_telemetry_logging_value); - ASSERT_EQ (conf.node.logging.network_rejected_logging_value, defaults.node.logging.network_rejected_logging_value); - ASSERT_EQ (conf.node.logging.rotation_size, defaults.node.logging.rotation_size); - ASSERT_EQ (conf.node.logging.single_line_record_value, defaults.node.logging.single_line_record_value); - ASSERT_EQ (conf.node.logging.stable_log_filename, defaults.node.logging.stable_log_filename); - ASSERT_EQ (conf.node.logging.timing_logging_value, defaults.node.logging.timing_logging_value); - ASSERT_EQ (conf.node.logging.active_update_value, defaults.node.logging.active_update_value); - ASSERT_EQ (conf.node.logging.upnp_details_logging_value, defaults.node.logging.upnp_details_logging_value); - ASSERT_EQ (conf.node.logging.vote_logging_value, defaults.node.logging.vote_logging_value); - ASSERT_EQ (conf.node.logging.rep_crawler_logging_value, defaults.node.logging.rep_crawler_logging_value); - ASSERT_EQ (conf.node.logging.work_generation_time_value, defaults.node.logging.work_generation_time_value); - ASSERT_EQ (conf.node.websocket_config.enabled, defaults.node.websocket_config.enabled); ASSERT_EQ (conf.node.websocket_config.address, defaults.node.websocket_config.address); ASSERT_EQ (conf.node.websocket_config.port, defaults.node.websocket_config.port); @@ -450,6 +423,8 @@ TEST (toml, daemon_config_deserialize_no_defaults) work_threads = 999 max_work_generate_multiplier = 1.0 max_queued_requests = 999 + request_aggregator_threads = 999 + max_unchecked_blocks = 999 frontiers_confirmation = "always" backlog_scan_batch_size = 999 backlog_scan_frequency = 999 @@ -614,6 +589,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.external_port, defaults.node.external_port); ASSERT_NE (conf.node.io_threads, defaults.node.io_threads); ASSERT_NE (conf.node.max_work_generate_multiplier, defaults.node.max_work_generate_multiplier); + ASSERT_NE (conf.node.max_unchecked_blocks, defaults.node.max_unchecked_blocks); ASSERT_NE (conf.node.frontiers_confirmation, defaults.node.frontiers_confirmation); ASSERT_NE (conf.node.network_threads, defaults.node.network_threads); ASSERT_NE (conf.node.background_threads, defaults.node.background_threads); @@ -639,38 +615,10 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.work_peers, defaults.node.work_peers); ASSERT_NE (conf.node.work_threads, defaults.node.work_threads); ASSERT_NE (conf.node.max_queued_requests, defaults.node.max_queued_requests); + ASSERT_NE (conf.node.request_aggregator_threads, defaults.node.request_aggregator_threads); ASSERT_NE (conf.node.backlog_scan_batch_size, defaults.node.backlog_scan_batch_size); ASSERT_NE (conf.node.backlog_scan_frequency, defaults.node.backlog_scan_frequency); - ASSERT_NE (conf.node.logging.bulk_pull_logging_value, defaults.node.logging.bulk_pull_logging_value); - ASSERT_NE (conf.node.logging.flush, defaults.node.logging.flush); - ASSERT_NE (conf.node.logging.insufficient_work_logging_value, defaults.node.logging.insufficient_work_logging_value); - ASSERT_NE (conf.node.logging.ledger_logging_value, defaults.node.logging.ledger_logging_value); - ASSERT_NE (conf.node.logging.ledger_duplicate_logging_value, defaults.node.logging.ledger_duplicate_logging_value); - ASSERT_NE (conf.node.logging.log_ipc_value, defaults.node.logging.log_ipc_value); - ASSERT_NE (conf.node.logging.log_to_cerr_value, defaults.node.logging.log_to_cerr_value); - ASSERT_NE (conf.node.logging.max_size, defaults.node.logging.max_size); - ASSERT_NE (conf.node.logging.min_time_between_log_output.count (), defaults.node.logging.min_time_between_log_output.count ()); - ASSERT_NE (conf.node.logging.network_logging_value, defaults.node.logging.network_logging_value); - ASSERT_NE (conf.node.logging.network_keepalive_logging_value, defaults.node.logging.network_keepalive_logging_value); - ASSERT_NE (conf.node.logging.network_message_logging_value, defaults.node.logging.network_message_logging_value); - ASSERT_NE (conf.node.logging.network_node_id_handshake_logging_value, defaults.node.logging.network_node_id_handshake_logging_value); - ASSERT_NE (conf.node.logging.network_telemetry_logging_value, defaults.node.logging.network_telemetry_logging_value); - ASSERT_NE (conf.node.logging.network_rejected_logging_value, defaults.node.logging.network_rejected_logging_value); - ASSERT_NE (conf.node.logging.network_packet_logging_value, defaults.node.logging.network_packet_logging_value); - ASSERT_NE (conf.node.logging.network_publish_logging_value, defaults.node.logging.network_publish_logging_value); - ASSERT_NE (conf.node.logging.network_timeout_logging_value, defaults.node.logging.network_timeout_logging_value); - ASSERT_NE (conf.node.logging.node_lifetime_tracing_value, defaults.node.logging.node_lifetime_tracing_value); - ASSERT_NE (conf.node.logging.rotation_size, defaults.node.logging.rotation_size); - ASSERT_NE (conf.node.logging.single_line_record_value, defaults.node.logging.single_line_record_value); - ASSERT_NE (conf.node.logging.stable_log_filename, defaults.node.logging.stable_log_filename); - ASSERT_NE (conf.node.logging.timing_logging_value, defaults.node.logging.timing_logging_value); - ASSERT_NE (conf.node.logging.active_update_value, defaults.node.logging.active_update_value); - ASSERT_NE (conf.node.logging.upnp_details_logging_value, defaults.node.logging.upnp_details_logging_value); - ASSERT_NE (conf.node.logging.vote_logging_value, defaults.node.logging.vote_logging_value); - ASSERT_NE (conf.node.logging.rep_crawler_logging_value, defaults.node.logging.rep_crawler_logging_value); - ASSERT_NE (conf.node.logging.work_generation_time_value, defaults.node.logging.work_generation_time_value); - ASSERT_NE (conf.node.websocket_config.enabled, defaults.node.websocket_config.enabled); ASSERT_NE (conf.node.websocket_config.address, defaults.node.websocket_config.address); ASSERT_NE (conf.node.websocket_config.port, defaults.node.websocket_config.port); @@ -975,3 +923,92 @@ TEST (toml, tls_config_defaults) ASSERT_EQ (conf.server_key_passphrase, defaults.server_key_passphrase); ASSERT_EQ (conf.server_dh_path, defaults.server_dh_path); } + +TEST (toml, log_config_defaults) +{ + std::stringstream ss; + + // A config with no values + ss << R"toml()toml"; + + nano::tomlconfig toml; + toml.read (ss); + nano::log_config confg{}; + nano::log_config defaults{}; + confg.deserialize_toml (toml); + + ASSERT_FALSE (toml.get_error ()) << toml.get_error ().get_message (); + + ASSERT_EQ (confg.default_level, defaults.default_level); + ASSERT_EQ (confg.flush_level, defaults.flush_level); + ASSERT_EQ (confg.levels, defaults.levels); + ASSERT_EQ (confg.console.enable, defaults.console.enable); + ASSERT_EQ (confg.console.colors, defaults.console.colors); + ASSERT_EQ (confg.console.to_cerr, defaults.console.to_cerr); + ASSERT_EQ (confg.file.enable, defaults.file.enable); + ASSERT_EQ (confg.file.max_size, defaults.file.max_size); + ASSERT_EQ (confg.file.rotation_count, defaults.file.rotation_count); +} + +TEST (toml, log_config_no_defaults) +{ + std::stringstream ss; + + // A config file with values that differs from defaults + ss << R"toml( + [log] + default_level = "trace" + + [log.console] + colors = false + enable = false + to_cerr = true + + [log.file] + enable = false + max_size = 999 + rotation_count = 999 + + [log.levels] + active_transactions = "trace" + blockprocessor = "trace" + )toml"; + + nano::tomlconfig toml; + toml.read (ss); + nano::log_config confg{}; + nano::log_config defaults{}; + confg.deserialize_toml (toml); + + ASSERT_FALSE (toml.get_error ()) << toml.get_error ().get_message (); + + ASSERT_NE (confg.default_level, defaults.default_level); + ASSERT_NE (confg.levels, defaults.levels); + ASSERT_NE (confg.console.enable, defaults.console.enable); + ASSERT_NE (confg.console.colors, defaults.console.colors); + ASSERT_NE (confg.console.to_cerr, defaults.console.to_cerr); + ASSERT_NE (confg.file.enable, defaults.file.enable); + ASSERT_NE (confg.file.max_size, defaults.file.max_size); + ASSERT_NE (confg.file.rotation_count, defaults.file.rotation_count); +} + +TEST (toml, log_config_no_required) +{ + std::stringstream ss; + + // A config with no values, only categories + ss << R"toml( + [log] + [log.console] + [log.file] + [log.levels] + )toml"; + + nano::tomlconfig toml; + toml.read (ss); + nano::log_config confg{}; + nano::log_config defaults{}; + confg.deserialize_toml (toml); + + ASSERT_FALSE (toml.get_error ()) << toml.get_error ().get_message (); +} \ No newline at end of file diff --git a/nano/core_test/uint256_union.cpp b/nano/core_test/uint256_union.cpp index c85c612704..86c82f6609 100644 --- a/nano/core_test/uint256_union.cpp +++ b/nano/core_test/uint256_union.cpp @@ -614,7 +614,7 @@ TEST (random_pool, generate_word64) for (auto i = 1; i < 10; ++i) { - ASSERT_TRUE (occurrences[i] > 0); + ASSERT_GT (occurrences[i], 0); } } @@ -624,5 +624,5 @@ TEST (random_pool, generate_word64_big_number) uint64_t min = static_cast (std::numeric_limits::max ()) + 1; uint64_t max = std::numeric_limits::max (); auto big_random = nano::random_pool::generate_word64 (min, max); - ASSERT_TRUE (big_random >= min); + ASSERT_GE (big_random, min); } diff --git a/nano/core_test/unchecked_map.cpp b/nano/core_test/unchecked_map.cpp index c9efc500a3..99777f653b 100644 --- a/nano/core_test/unchecked_map.cpp +++ b/nano/core_test/unchecked_map.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -15,11 +15,13 @@ using namespace std::chrono_literals; namespace { +unsigned max_unchecked_blocks = 65536; + class context { public: context () : - unchecked{ stats, false } + unchecked{ max_unchecked_blocks, stats, false } { } nano::stats stats; @@ -36,7 +38,7 @@ std::shared_ptr block () .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); } } @@ -55,7 +57,7 @@ TEST (unchecked_map, put_one) TEST (block_store, one_bootstrap) { nano::test::system system{}; - nano::unchecked_map unchecked{ system.stats, false }; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; nano::block_builder builder; auto block1 = builder .send () @@ -64,7 +66,7 @@ TEST (block_store, one_bootstrap) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); unchecked.put (block1->hash (), nano::unchecked_info{ block1 }); auto check_block_is_listed = [&] (nano::block_hash const & block_hash_a) { return unchecked.get (block_hash_a).size () > 0; @@ -88,7 +90,7 @@ TEST (block_store, one_bootstrap) TEST (unchecked, simple) { nano::test::system system{}; - nano::unchecked_map unchecked{ system.stats, false }; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; nano::block_builder builder; auto block = builder .send () @@ -97,7 +99,7 @@ TEST (unchecked, simple) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); // Asserts the block wasn't added yet to the unchecked table auto block_listing1 = unchecked.get (block->previous ()); ASSERT_TRUE (block_listing1.empty ()); @@ -129,7 +131,7 @@ TEST (unchecked, multiple) // Don't test this in rocksdb mode GTEST_SKIP (); } - nano::unchecked_map unchecked{ system.stats, false }; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; nano::block_builder builder; auto block = builder .send () @@ -138,28 +140,28 @@ TEST (unchecked, multiple) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); // Asserts the block wasn't added yet to the unchecked table auto block_listing1 = unchecked.get (block->previous ()); ASSERT_TRUE (block_listing1.empty ()); // Enqueues the first block unchecked.put (block->previous (), nano::unchecked_info (block)); // Enqueues a second block - unchecked.put (block->source (), nano::unchecked_info (block)); + unchecked.put (6, nano::unchecked_info (block)); auto check_block_is_listed = [&] (nano::block_hash const & block_hash_a) { return unchecked.get (block_hash_a).size () > 0; }; // Waits for and asserts the first block gets saved in the database ASSERT_TIMELY (5s, check_block_is_listed (block->previous ())); // Waits for and asserts the second block gets saved in the database - ASSERT_TIMELY (5s, check_block_is_listed (block->source ())); + ASSERT_TIMELY (5s, check_block_is_listed (6)); } // This test ensures that a block can't occur twice in the unchecked table. TEST (unchecked, double_put) { nano::test::system system{}; - nano::unchecked_map unchecked{ system.stats, false }; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; nano::block_builder builder; auto block = builder .send () @@ -168,7 +170,7 @@ TEST (unchecked, double_put) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); // Asserts the block wasn't added yet to the unchecked table auto block_listing1 = unchecked.get (block->previous ()); ASSERT_TRUE (block_listing1.empty ()); @@ -190,7 +192,7 @@ TEST (unchecked, double_put) TEST (unchecked, multiple_get) { nano::test::system system{}; - nano::unchecked_map unchecked{ system.stats, false }; + nano::unchecked_map unchecked{ max_unchecked_blocks, system.stats, false }; // Instantiates three blocks nano::block_builder builder; auto block1 = builder @@ -200,7 +202,7 @@ TEST (unchecked, multiple_get) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); auto block2 = builder .send () .previous (3) @@ -208,7 +210,7 @@ TEST (unchecked, multiple_get) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); auto block3 = builder .send () .previous (5) @@ -216,7 +218,7 @@ TEST (unchecked, multiple_get) .balance (2) .sign (nano::keypair ().prv, 4) .work (5) - .build_shared (); + .build (); // Add the blocks' info to the unchecked table unchecked.put (block1->previous (), nano::unchecked_info (block1)); // unchecked1 unchecked.put (block1->hash (), nano::unchecked_info (block1)); // unchecked2 diff --git a/nano/core_test/utility.cpp b/nano/core_test/utility.cpp index 1bd6a50c2b..730714dc83 100644 --- a/nano/core_test/utility.cpp +++ b/nano/core_test/utility.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -346,3 +347,16 @@ TEST (relaxed_atomic_integral, many_threads) // Check values ASSERT_EQ (0, atomic); } + +TEST (pending_key, sorting) +{ + nano::pending_key one{ 1, 2 }; + nano::pending_key two{ 1, 3 }; + nano::pending_key three{ 2, 1 }; + ASSERT_LT (one, two); + ASSERT_LT (one, three); + ASSERT_LT (two, three); + nano::pending_key one_same{ 1, 2 }; + ASSERT_EQ (std::hash{}(one), std::hash{}(one_same)); + ASSERT_NE (std::hash{}(one), std::hash{}(two)); +} diff --git a/nano/core_test/vote_processor.cpp b/nano/core_test/vote_processor.cpp index 210db3cd17..f755eb8ac0 100644 --- a/nano/core_test/vote_processor.cpp +++ b/nano/core_test/vote_processor.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include #include @@ -14,7 +16,7 @@ TEST (vote_processor, codes) nano::test::system system (1); auto & node (*system.nodes[0]); auto blocks = nano::test::setup_chain (system, node, 1, nano::dev::genesis_key, false); - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ blocks[0]->hash () })); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { blocks[0] }, nano::vote::timestamp_min * 1, 0); auto vote_invalid = std::make_shared (*vote); vote_invalid->signature.bytes[0] ^= 1; auto channel (std::make_shared (node, node)); @@ -90,7 +92,7 @@ TEST (vote_processor, no_capacity) node_flags.vote_processor_capacity = 0; auto & node (*system.add_node (node_flags)); nano::keypair key; - auto vote (std::make_shared (key.pub, key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ nano::dev::genesis->hash () })); + auto vote = nano::test::make_vote (key, { nano::dev::genesis }, nano::vote::timestamp_min * 1, 0); auto channel (std::make_shared (node, node)); ASSERT_TRUE (node.vote_processor.vote (vote, channel)); } @@ -102,7 +104,7 @@ TEST (vote_processor, overflow) node_flags.vote_processor_capacity = 1; auto & node (*system.add_node (node_flags)); nano::keypair key; - auto vote (std::make_shared (key.pub, key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ nano::dev::genesis->hash () })); + auto vote = nano::test::make_vote (key, { nano::dev::genesis }, nano::vote::timestamp_min * 1, 0); auto channel (std::make_shared (node, node)); auto start_time = std::chrono::system_clock::now (); @@ -124,19 +126,17 @@ TEST (vote_processor, overflow) ASSERT_LT (std::chrono::system_clock::now () - start_time, 10s); } -namespace nano -{ TEST (vote_processor, weights) { nano::test::system system (4); auto & node (*system.nodes[0]); // Create representatives of different weight levels - // The online stake will be the minimum configurable due to online_reps sampling in tests - auto const online = node.config.online_weight_minimum.number (); - auto const level0 = online / 5000; // 0.02% - auto const level1 = online / 500; // 0.2% - auto const level2 = online / 50; // 2% + // FIXME: Using `online_weight_minimum` because calculation of trended and online weight is broken when running tests + auto const stake = node.config.online_weight_minimum.number (); + auto const level0 = stake / 5000; // 0.02% + auto const level1 = stake / 500; // 0.2% + auto const level2 = stake / 50; // 2% nano::keypair key0; nano::keypair key1; @@ -155,24 +155,15 @@ TEST (vote_processor, weights) // Wait for representatives ASSERT_TIMELY_EQ (10s, node.ledger.cache.rep_weights.get_rep_amounts ().size (), 4); - node.vote_processor.calculate_weights (); - - ASSERT_EQ (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key0.pub)); - ASSERT_EQ (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key0.pub)); - ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key0.pub)); - ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key1.pub)); - ASSERT_EQ (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key1.pub)); - ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key1.pub)); + // Wait for rep tiers to be updated + node.stats.clear (); + ASSERT_TIMELY (5s, node.stats.count (nano::stat::type::rep_tiers, nano::stat::detail::updated) >= 2); - ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key2.pub)); - ASSERT_NE (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key2.pub)); - ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key2.pub)); - - ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (nano::dev::genesis_key.pub)); - ASSERT_NE (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (nano::dev::genesis_key.pub)); - ASSERT_NE (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (nano::dev::genesis_key.pub)); -} + ASSERT_EQ (node.rep_tiers.tier (key0.pub), nano::rep_tier::none); + ASSERT_EQ (node.rep_tiers.tier (key1.pub), nano::rep_tier::tier_1); + ASSERT_EQ (node.rep_tiers.tier (key2.pub), nano::rep_tier::tier_2); + ASSERT_EQ (node.rep_tiers.tier (nano::dev::genesis_key.pub), nano::rep_tier::tier_3); } // Issue that tracks last changes on this test: https://github.com/nanocurrency/nano-node/issues/3485 @@ -204,7 +195,7 @@ TEST (vote_processor, no_broadcast_local) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (ec); ASSERT_FALSE (ec); - ASSERT_EQ (nano::process_result::progress, node.process_local (send).value ().code); + ASSERT_EQ (nano::block_status::progress, node.process_local (send).value ()); ASSERT_TIMELY (10s, !node.active.empty ()); ASSERT_EQ (2 * node.config.vote_minimum.number (), node.weight (nano::dev::genesis_key.pub)); // Insert account in wallet. Votes on node are not enabled. @@ -257,7 +248,7 @@ TEST (vote_processor, local_broadcast_without_a_representative) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (ec); ASSERT_FALSE (ec); - ASSERT_EQ (nano::process_result::progress, node.process_local (send).value ().code); + ASSERT_EQ (nano::block_status::progress, node.process_local (send).value ()); ASSERT_TIMELY (10s, !node.active.empty ()); ASSERT_EQ (node.config.vote_minimum, node.weight (nano::dev::genesis_key.pub)); node.start_election (send); @@ -305,7 +296,7 @@ TEST (vote_processor, no_broadcast_local_with_a_principal_representative) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (ec); ASSERT_FALSE (ec); - ASSERT_EQ (nano::process_result::progress, node.process_local (send).value ().code); + ASSERT_EQ (nano::block_status::progress, node.process_local (send).value ()); ASSERT_TIMELY (10s, !node.active.empty ()); ASSERT_EQ (nano::dev::constants.genesis_amount - 2 * node.config.vote_minimum.number (), node.weight (nano::dev::genesis_key.pub)); // Insert account in wallet. Votes on node are not enabled. diff --git a/nano/core_test/voting.cpp b/nano/core_test/voting.cpp index 99311635ab..d6d644292e 100644 --- a/nano/core_test/voting.cpp +++ b/nano/core_test/voting.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include @@ -158,7 +160,7 @@ TEST (vote_spacing, vote_generator) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -167,13 +169,13 @@ TEST (vote_spacing, vote_generator) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); ASSERT_EQ (0, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_broadcasts)); node.generator.add (nano::dev::genesis->hash (), send1->hash ()); ASSERT_TIMELY_EQ (3s, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_broadcasts), 1); ASSERT_FALSE (node.ledger.rollback (node.store.tx_begin_write (), send1->hash ())); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send2).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send2)); node.generator.add (nano::dev::genesis->hash (), send2->hash ()); ASSERT_TIMELY_EQ (3s, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_spacing), 1); ASSERT_EQ (1, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_broadcasts)); @@ -202,7 +204,7 @@ TEST (vote_spacing, rapid) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder.make_block () .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) @@ -211,12 +213,12 @@ TEST (vote_spacing, rapid) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send1)); node.generator.add (nano::dev::genesis->hash (), send1->hash ()); ASSERT_TIMELY_EQ (3s, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_broadcasts), 1); ASSERT_FALSE (node.ledger.rollback (node.store.tx_begin_write (), send1->hash ())); - ASSERT_EQ (nano::process_result::progress, node.ledger.process (node.store.tx_begin_write (), *send2).code); + ASSERT_EQ (nano::block_status::progress, node.ledger.process (node.store.tx_begin_write (), send2)); node.generator.add (nano::dev::genesis->hash (), send2->hash ()); ASSERT_TIMELY_EQ (3s, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_spacing), 1); ASSERT_TIMELY_EQ (3s, 1, node.stats.count (nano::stat::type::vote_generator, nano::stat::detail::generator_broadcasts)); diff --git a/nano/core_test/wallet.cpp b/nano/core_test/wallet.cpp index b750538b12..de2cfb42c0 100644 --- a/nano/core_test/wallet.cpp +++ b/nano/core_test/wallet.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -12,11 +14,11 @@ unsigned constexpr nano::wallet_store::version_current; TEST (wallet, no_special_keys_accounts) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::keypair key1; ASSERT_FALSE (wallet.exists (transaction, key1.pub)); @@ -33,11 +35,11 @@ TEST (wallet, no_special_keys_accounts) TEST (wallet, no_key) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::keypair key1; nano::raw_key prv1; @@ -48,11 +50,11 @@ TEST (wallet, no_key) TEST (wallet, fetch_locked) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_TRUE (wallet.valid_password (transaction)); nano::keypair key1; ASSERT_EQ (key1.pub, wallet.insert_adhoc (transaction, key1.prv)); @@ -70,11 +72,11 @@ TEST (wallet, fetch_locked) TEST (wallet, retrieval) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::keypair key1; ASSERT_TRUE (wallet.valid_password (transaction)); @@ -92,11 +94,11 @@ TEST (wallet, retrieval) TEST (wallet, empty_iteration) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); auto i (wallet.begin (transaction)); auto j (wallet.end ()); @@ -106,11 +108,11 @@ TEST (wallet, empty_iteration) TEST (wallet, one_item_iteration) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::keypair key1; wallet.insert_adhoc (transaction, key1.prv); @@ -128,7 +130,7 @@ TEST (wallet, one_item_iteration) TEST (wallet, two_item_iteration) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); nano::keypair key1; nano::keypair key2; @@ -138,7 +140,7 @@ TEST (wallet, two_item_iteration) nano::kdf kdf{ nano::dev::network_params.kdf_work }; { auto transaction (env.tx_begin_write ()); - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); wallet.insert_adhoc (transaction, key1.prv); wallet.insert_adhoc (transaction, key2.prv); @@ -181,7 +183,7 @@ TEST (wallet, spend_all_one) auto transaction (node1.store.tx_begin_read ()); auto info2 = node1.ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_NE (latest1, info2->head); - auto block (node1.store.block.get (transaction, info2->head)); + auto block = node1.ledger.block (transaction, info2->head); ASSERT_NE (nullptr, block); ASSERT_EQ (latest1, block->previous ()); ASSERT_TRUE (info2->balance.is_zero ()); @@ -216,26 +218,13 @@ TEST (wallet, spend) auto info2 = node1.ledger.account_info (transaction, nano::dev::genesis_key.pub); ASSERT_TRUE (info2); ASSERT_NE (latest1, info2->head); - auto block (node1.store.block.get (transaction, info2->head)); + auto block = node1.ledger.block (transaction, info2->head); ASSERT_NE (nullptr, block); ASSERT_EQ (latest1, block->previous ()); ASSERT_TRUE (info2->balance.is_zero ()); ASSERT_EQ (0, node1.balance (nano::dev::genesis_key.pub)); } -TEST (wallet, change) -{ - nano::test::system system (1); - system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - nano::keypair key2; - auto block1 (system.nodes[0]->rep_block (nano::dev::genesis_key.pub)); - ASSERT_FALSE (block1.is_zero ()); - ASSERT_NE (nullptr, system.wallet (0)->change_action (nano::dev::genesis_key.pub, key2.pub)); - auto block2 (system.nodes[0]->rep_block (nano::dev::genesis_key.pub)); - ASSERT_FALSE (block2.is_zero ()); - ASSERT_NE (block1, block2); -} - TEST (wallet, partial_spend) { nano::test::system system (1); @@ -267,11 +256,11 @@ TEST (wallet, spend_no_previous) TEST (wallet, find_none) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::account account (1000); ASSERT_EQ (wallet.end (), wallet.find (transaction, account)); @@ -280,11 +269,11 @@ TEST (wallet, find_none) TEST (wallet, find_existing) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::keypair key1; ASSERT_FALSE (wallet.exists (transaction, key1.pub)); @@ -299,11 +288,11 @@ TEST (wallet, find_existing) TEST (wallet, rekey) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::raw_key password; wallet.password.value (password); @@ -371,11 +360,11 @@ TEST (account, encode_fail) TEST (wallet, hash_password) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); nano::raw_key hash1; wallet.derive_key (hash1, transaction, ""); @@ -420,30 +409,30 @@ TEST (fan, change) TEST (wallet, reopen_default_password) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); auto transaction (env.tx_begin_write ()); ASSERT_FALSE (init); nano::kdf kdf{ nano::dev::network_params.kdf_work }; { - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); ASSERT_TRUE (wallet.valid_password (transaction)); } { bool init; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); ASSERT_TRUE (wallet.valid_password (transaction)); } { - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); wallet.rekey (transaction, ""); ASSERT_TRUE (wallet.valid_password (transaction)); } { bool init; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (init); ASSERT_FALSE (wallet.valid_password (transaction)); wallet.attempt_password (transaction, " "); @@ -456,14 +445,14 @@ TEST (wallet, reopen_default_password) TEST (wallet, representative) { auto error (false); - nano::store::lmdb::env env (error, nano::unique_path ()); + nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (error); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (error); ASSERT_FALSE (wallet.is_representative (transaction)); - ASSERT_EQ (nano::dev::genesis->account (), wallet.representative (transaction)); + ASSERT_EQ (nano::dev::genesis_key.pub, wallet.representative (transaction)); ASSERT_FALSE (wallet.is_representative (transaction)); nano::keypair key; wallet.representative_set (transaction, key.pub); @@ -477,15 +466,15 @@ TEST (wallet, representative) TEST (wallet, serialize_json_empty) { auto error (false); - nano::store::lmdb::env env (error, nano::unique_path ()); + nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (error); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (error); std::string serialized; wallet1.serialize_json (transaction, serialized); - nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized); + nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "1", serialized); ASSERT_FALSE (error); nano::raw_key password1; nano::raw_key password2; @@ -502,17 +491,17 @@ TEST (wallet, serialize_json_empty) TEST (wallet, serialize_json_one) { auto error (false); - nano::store::lmdb::env env (error, nano::unique_path ()); + nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (error); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (error); nano::keypair key; wallet1.insert_adhoc (transaction, key.prv); std::string serialized; wallet1.serialize_json (transaction, serialized); - nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized); + nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "1", serialized); ASSERT_FALSE (error); nano::raw_key password1; nano::raw_key password2; @@ -531,18 +520,18 @@ TEST (wallet, serialize_json_one) TEST (wallet, serialize_json_password) { auto error (false); - nano::store::lmdb::env env (error, nano::unique_path ()); + nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (error); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (error); nano::keypair key; wallet1.rekey (transaction, "password"); wallet1.insert_adhoc (transaction, key.prv); std::string serialized; wallet1.serialize_json (transaction, serialized); - nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized); + nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "1", serialized); ASSERT_FALSE (error); ASSERT_FALSE (wallet2.valid_password (transaction)); ASSERT_FALSE (wallet2.attempt_password (transaction, "password")); @@ -564,15 +553,15 @@ TEST (wallet, serialize_json_password) TEST (wallet_store, move) { auto error (false); - nano::store::lmdb::env env (error, nano::unique_path ()); + nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (error); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); ASSERT_FALSE (error); nano::keypair key1; wallet1.insert_adhoc (transaction, key1.prv); - nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1"); + nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "1"); ASSERT_FALSE (error); nano::keypair key2; wallet2.insert_adhoc (transaction, key2.prv); @@ -722,11 +711,11 @@ TEST (wallet, insert_locked) TEST (wallet, deterministic_keys) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); auto key1 = wallet.deterministic_key (transaction, 0); auto key2 = wallet.deterministic_key (transaction, 0); ASSERT_EQ (key1, key2); @@ -765,11 +754,11 @@ TEST (wallet, deterministic_keys) TEST (wallet, reseed) { bool init; - nano::store::lmdb::env env (init, nano::unique_path ()); + nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb"); ASSERT_FALSE (init); auto transaction (env.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0"); + nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); nano::raw_key seed1; seed1 = 1; nano::raw_key seed2; @@ -946,7 +935,7 @@ TEST (wallet, change_seed) wallet->insert_adhoc (nano::dev::genesis_key.prv, false); auto block (wallet->send_action (nano::dev::genesis_key.pub, pub, 100)); ASSERT_NE (nullptr, block); - system.nodes[0]->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*system.nodes[0], { block })); { auto transaction (wallet->wallets.tx_begin_write ()); wallet->change_seed (transaction, seed1); @@ -980,7 +969,7 @@ TEST (wallet, deterministic_restore) wallet->insert_adhoc (nano::dev::genesis_key.prv, false); auto block (wallet->send_action (nano::dev::genesis_key.pub, pub, 100)); ASSERT_NE (nullptr, block); - system.nodes[0]->block_processor.flush (); + ASSERT_TIMELY (5s, nano::test::exists (*system.nodes[0], { block })); { auto transaction (wallet->wallets.tx_begin_write ()); wallet->deterministic_restore (transaction); @@ -1013,7 +1002,7 @@ TEST (wallet, epoch_2_validation) ASSERT_EQ (nano::epoch::epoch_2, send->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_0, send->sideband ().source_epoch); // Not used for send state blocks - auto receive = wallet.receive_action (send->hash (), nano::dev::genesis_key.pub, amount, send->link ().as_account (), 1); + auto receive = wallet.receive_action (send->hash (), nano::dev::genesis_key.pub, amount, send->destination (), 1); ASSERT_NE (nullptr, receive); if (nano::dev::network_params.work.difficulty (*receive) < node.network_params.work.base) { @@ -1055,7 +1044,7 @@ TEST (wallet, epoch_2_receive_propagation) auto amount = node.config.receive_minimum.number (); auto send1 = wallet.send_action (nano::dev::genesis_key.pub, key.pub, amount, 1); ASSERT_NE (nullptr, send1); - ASSERT_NE (nullptr, wallet.receive_action (send1->hash (), nano::dev::genesis_key.pub, amount, send1->link ().as_account (), 1)); + ASSERT_NE (nullptr, wallet.receive_action (send1->hash (), nano::dev::genesis_key.pub, amount, send1->destination (), 1)); // Upgrade the genesis account to epoch 2 auto epoch2 = system.upgrade_genesis_epoch (node, nano::epoch::epoch_2); @@ -1065,7 +1054,7 @@ TEST (wallet, epoch_2_receive_propagation) auto send2 = wallet.send_action (nano::dev::genesis_key.pub, key.pub, amount, 1); ASSERT_NE (nullptr, send2); - auto receive2 = wallet.receive_action (send2->hash (), key.pub, amount, send2->link ().as_account (), 1); + auto receive2 = wallet.receive_action (send2->hash (), key.pub, amount, send2->destination (), 1); ASSERT_NE (nullptr, receive2); if (nano::dev::network_params.work.difficulty (*receive2) < node.network_params.work.base) { @@ -1114,11 +1103,11 @@ TEST (wallet, epoch_2_receive_unopened) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (key.pub, node.network_params.work.epoch_2)) .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*epoch2_unopened).code); + ASSERT_EQ (nano::block_status::progress, node.process (epoch2_unopened)); wallet.insert_adhoc (key.prv, false); - auto receive1 = wallet.receive_action (send1->hash (), key.pub, amount, send1->link ().as_account (), 1); + auto receive1 = wallet.receive_action (send1->hash (), key.pub, amount, send1->destination (), 1); ASSERT_NE (nullptr, receive1); if (nano::dev::network_params.work.difficulty (*receive1) < node.network_params.work.base) { @@ -1167,15 +1156,15 @@ TEST (wallet, search_receivable) wallet.insert_adhoc (nano::dev::genesis_key.prv); nano::block_builder builder; auto send = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - node.config.receive_minimum.number ()) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); // Pending search should start an election ASSERT_TRUE (node.active.empty ()); @@ -1184,7 +1173,7 @@ TEST (wallet, search_receivable) ASSERT_TIMELY (5s, election = node.active.election (send->qualified_root ())); // Erase the key so the confirmation does not trigger an automatic receive - wallet.store.erase (node.wallets.tx_begin_write (), nano::dev::genesis->account ()); + wallet.store.erase (node.wallets.tx_begin_write (), nano::dev::genesis_key.pub); // Now confirm the election election->force_confirm (); @@ -1197,12 +1186,12 @@ TEST (wallet, search_receivable) // Pending search should create the receive block ASSERT_EQ (2, node.ledger.cache.block_count); ASSERT_FALSE (wallet.search_receivable (wallet.wallets.tx_begin_read ())); - ASSERT_TIMELY_EQ (3s, node.balance (nano::dev::genesis->account ()), nano::dev::constants.genesis_amount); - auto receive_hash = node.ledger.latest (node.store.tx_begin_read (), nano::dev::genesis->account ()); + ASSERT_TIMELY_EQ (3s, node.balance (nano::dev::genesis_key.pub), nano::dev::constants.genesis_amount); + auto receive_hash = node.ledger.latest (node.store.tx_begin_read (), nano::dev::genesis_key.pub); auto receive = node.block (receive_hash); ASSERT_NE (nullptr, receive); ASSERT_EQ (receive->sideband ().height, 3); - ASSERT_EQ (send->hash (), receive->link ().as_block_hash ()); + ASSERT_EQ (send->hash (), receive->source ()); } TEST (wallet, receive_pruned) @@ -1236,11 +1225,11 @@ TEST (wallet, receive_pruned) } ASSERT_EQ (1, node2.ledger.cache.pruned_count); ASSERT_TRUE (node2.ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_FALSE (node2.store.block.exists (node2.store.tx_begin_read (), send1->hash ())); + ASSERT_FALSE (node2.ledger.block_exists (node2.store.tx_begin_read (), send1->hash ())); wallet2.insert_adhoc (key.prv, false); - auto open1 = wallet2.receive_action (send1->hash (), key.pub, amount, send1->link ().as_account (), 1); + auto open1 = wallet2.receive_action (send1->hash (), key.pub, amount, send1->destination (), 1); ASSERT_NE (nullptr, open1); ASSERT_EQ (amount, node2.ledger.balance (node2.store.tx_begin_read (), open1->hash ())); ASSERT_TIMELY_EQ (5s, node2.ledger.cache.cemented_count, 4); diff --git a/nano/core_test/wallets.cpp b/nano/core_test/wallets.cpp index 8b8d7c96ff..af4b953b1f 100644 --- a/nano/core_test/wallets.cpp +++ b/nano/core_test/wallets.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -110,7 +112,7 @@ TEST (wallets, vote_minimum) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send1)); auto open1 = builder .state () .account (key1.pub) @@ -121,7 +123,7 @@ TEST (wallets, vote_minimum) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1.process (*open1).code); + ASSERT_EQ (nano::block_status::progress, node1.process (open1)); // send2 with amount vote_minimum - 1 (not voting representative) auto send2 = builder .state () @@ -133,7 +135,7 @@ TEST (wallets, vote_minimum) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1.process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node1.process (send2)); auto open2 = builder .state () .account (key2.pub) @@ -144,7 +146,7 @@ TEST (wallets, vote_minimum) .sign (key2.prv, key2.pub) .work (*system.work.generate (key2.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1.process (*open2).code); + ASSERT_EQ (nano::block_status::progress, node1.process (open2)); auto wallet (node1.wallets.items.begin ()->second); nano::unique_lock representatives_lk (wallet->representatives_mutex); ASSERT_EQ (0, wallet->representatives.size ()); @@ -204,15 +206,15 @@ TEST (wallets, search_receivable) wallet->insert_adhoc (nano::dev::genesis_key.prv); nano::block_builder builder; auto send = builder.state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - node.config.receive_minimum.number ()) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node.process (*send).code); + ASSERT_EQ (nano::block_status::progress, node.process (send)); // Pending search should start an election ASSERT_TRUE (node.active.empty ()); @@ -228,7 +230,7 @@ TEST (wallets, search_receivable) ASSERT_TIMELY (5s, election = node.active.election (send->qualified_root ())); // Erase the key so the confirmation does not trigger an automatic receive - wallet->store.erase (node.wallets.tx_begin_write (), nano::dev::genesis->account ()); + wallet->store.erase (node.wallets.tx_begin_write (), nano::dev::genesis_key.pub); // Now confirm the election election->force_confirm (); @@ -248,11 +250,11 @@ TEST (wallets, search_receivable) { node.wallets.search_receivable (wallet_id); } - ASSERT_TIMELY_EQ (3s, node.balance (nano::dev::genesis->account ()), nano::dev::constants.genesis_amount); - auto receive_hash = node.ledger.latest (node.store.tx_begin_read (), nano::dev::genesis->account ()); + ASSERT_TIMELY_EQ (3s, node.balance (nano::dev::genesis_key.pub), nano::dev::constants.genesis_amount); + auto receive_hash = node.ledger.latest (node.store.tx_begin_read (), nano::dev::genesis_key.pub); auto receive = node.block (receive_hash); ASSERT_NE (nullptr, receive); ASSERT_EQ (receive->sideband ().height, 3); - ASSERT_EQ (send->hash (), receive->link ().as_block_hash ()); + ASSERT_EQ (send->hash (), receive->source ()); } } diff --git a/nano/core_test/websocket.cpp b/nano/core_test/websocket.cpp index f069c6539c..0d147dba4f 100644 --- a/nano/core_test/websocket.cpp +++ b/nano/core_test/websocket.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -99,7 +100,7 @@ TEST (websocket, confirmation) .balance (balance) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); } @@ -118,7 +119,7 @@ TEST (websocket, confirmation) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); } @@ -158,7 +159,7 @@ TEST (websocket, started_election) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::publish publish1{ nano::dev::network_params.network, send1 }; auto channel1 = std::make_shared (*node1); node1->network.inbound (publish1, channel1); @@ -206,12 +207,11 @@ TEST (websocket, stopped_election) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); nano::publish publish1{ nano::dev::network_params.network, send1 }; auto channel1 = std::make_shared (*node1); node1->network.inbound (publish1, channel1); - node1->block_processor.flush (); - ASSERT_TIMELY (1s, node1->active.election (send1->qualified_root ())); + ASSERT_TIMELY (5s, node1->active.election (send1->qualified_root ())); node1->active.erase (*send1); ASSERT_TIMELY_EQ (5s, future.wait_for (0s), std::future_status::ready); @@ -265,7 +265,7 @@ TEST (websocket, confirmation_options) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); previous = send->hash (); @@ -298,7 +298,7 @@ TEST (websocket, confirmation_options) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); previous = send->hash (); @@ -361,7 +361,7 @@ TEST (websocket, confirmation_options) .balance (balance) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); previous = send->hash (); } @@ -407,7 +407,7 @@ TEST (websocket, confirmation_options_votes) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); previous = send->hash (); @@ -494,7 +494,7 @@ TEST (websocket, confirmation_options_sideband) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); previous = send->hash (); @@ -575,7 +575,7 @@ TEST (websocket, confirmation_options_update) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); @@ -593,7 +593,7 @@ TEST (websocket, confirmation_options_update) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send2); @@ -635,7 +635,7 @@ TEST (websocket, vote) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); @@ -673,7 +673,7 @@ TEST (websocket, vote_options_type) ASSERT_TIMELY (5s, ack_ready); // Custom made votes for simplicity - auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ nano::dev::genesis->hash () })); + auto vote = nano::test::make_vote (nano::dev::genesis_key, { nano::dev::genesis }, 0, 0); nano::websocket::message_builder builder; auto msg (builder.vote_received (vote, nano::vote_code::replay)); node1->websocket.server->broadcast (msg); @@ -737,7 +737,7 @@ TEST (websocket, vote_options_representatives) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); node1->process_active (send); }; confirm_block (); @@ -796,7 +796,7 @@ TEST (websocket, work) // Generate work nano::block_hash hash{ 1 }; auto work (node1->work_generate_blocking (hash)); - ASSERT_TRUE (work.is_initialized ()); + ASSERT_TRUE (work.has_value ()); // Wait for the work notification ASSERT_TIMELY_EQ (5s, future.wait_for (0s), std::future_status::ready); @@ -827,7 +827,7 @@ TEST (websocket, work) nano::from_string_hex (result.get ("difficulty"), result_difficulty); ASSERT_GE (result_difficulty, node1->default_difficulty (nano::work_version::work_1)); ASSERT_NEAR (result.get ("multiplier"), nano::difficulty::to_multiplier (result_difficulty, node1->default_difficulty (nano::work_version::work_1)), 1e-6); - ASSERT_EQ (result.get ("work"), nano::to_string_hex (work.get ())); + ASSERT_EQ (result.get ("work"), nano::to_string_hex (work.value ())); ASSERT_EQ (1, contents.count ("bad_peers")); auto & bad_peers = contents.get_child ("bad_peers"); @@ -1060,9 +1060,9 @@ TEST (websocket, new_unconfirmed_block) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); - ASSERT_EQ (nano::process_result::progress, node1->process_local (send1).value ().code); + ASSERT_EQ (nano::block_status::progress, node1->process_local (send1).value ()); ASSERT_TIMELY_EQ (5s, future.wait_for (0s), std::future_status::ready); diff --git a/nano/core_test/work_pool.cpp b/nano/core_test/work_pool.cpp index 99fafac728..63eae4cf7f 100644 --- a/nano/core_test/work_pool.cpp +++ b/nano/core_test/work_pool.cpp @@ -1,9 +1,8 @@ #include #include -#include +#include #include #include -#include #include #include #include @@ -13,6 +12,7 @@ #include +// produce one proof of work for a block and check that its difficulty is higher than the base difficulty TEST (work, one) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -28,6 +28,7 @@ TEST (work, one) ASSERT_LT (nano::dev::network_params.work.threshold_base (block->work_version ()), nano::dev::network_params.work.difficulty (*block)); } +// create a work_pool with zero threads and check that pool.generate returns no result TEST (work, disabled) { nano::work_pool pool{ nano::dev::network_params.network, 0 }; @@ -35,6 +36,7 @@ TEST (work, disabled) ASSERT_FALSE (result.is_initialized ()); } +// create a block with bad pow then fix it and check that it validates TEST (work, validate) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -49,19 +51,19 @@ TEST (work, validate) .build (); ASSERT_LT (nano::dev::network_params.work.difficulty (*send_block), nano::dev::network_params.work.threshold_base (send_block->work_version ())); send_block->block_work_set (*pool.generate (send_block->root ())); - ASSERT_LT (nano::dev::network_params.work.threshold_base (send_block->work_version ()), nano::dev::network_params.work.difficulty (*send_block)); + ASSERT_GE (nano::dev::network_params.work.difficulty (*send_block), nano::dev::network_params.work.threshold_base (send_block->work_version ())); } +// repeatedly start and cancel a work calculation and check that the callback is eventually called TEST (work, cancel) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto iterations (0); - auto done (false); + const nano::root key (1); + auto iterations = 0; + auto done = false; while (!done) { - nano::root key (1); - pool.generate ( - nano::work_version::work_1, key, nano::dev::network_params.work.base, [&done] (boost::optional work_a) { + pool.generate (nano::work_version::work_1, key, nano::dev::network_params.work.base, [&done] (boost::optional work_a) { done = !work_a; }); pool.cancel (key); @@ -70,7 +72,7 @@ TEST (work, cancel) } } -TEST (work, cancel_many) +TEST (work, cancel_one_out_of_many) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; nano::root key1 (1); @@ -88,61 +90,66 @@ TEST (work, cancel_many) pool.cancel (key1); } +// check that opencl hardware offloading works TEST (work, opencl) { - nano::logging logging; - logging.init (nano::unique_path ()); - nano::logger_mt logger; - bool error (false); + nano::logger logger; + bool error = false; nano::opencl_environment environment (error); ASSERT_TRUE (!error || !nano::opencl_loaded); - if (!environment.platforms.empty () && !environment.platforms.begin ()->devices.empty ()) + + if (environment.platforms.empty () || environment.platforms.begin ()->devices.empty ()) { - nano::opencl_config config (0, 0, 16 * 1024); - auto opencl (nano::opencl_work::create (true, config, logger, nano::dev::network_params.work)); - if (opencl != nullptr) - { - // 0 threads, should add 1 for managing OpenCL - nano::work_pool pool{ nano::dev::network_params.network, 0, std::chrono::nanoseconds (0), [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { - return opencl->generate_work (version_a, root_a, difficulty_a); - } }; - ASSERT_NE (nullptr, pool.opencl); - nano::root root; - uint64_t difficulty (0xff00000000000000); - uint64_t difficulty_add (0x000f000000000000); - for (auto i (0); i < 16; ++i) - { - nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ()); - auto result (*pool.generate (nano::work_version::work_1, root, difficulty)); - ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, result), difficulty); - difficulty += difficulty_add; - } - } - else - { - std::cerr << "Error starting OpenCL test" << std::endl; - } + GTEST_SKIP () << "Device with OpenCL support not found. Skipping OpenCL test" << std::endl; } - else + + nano::opencl_config config (0, 0, 16 * 1024); + auto opencl = nano::opencl_work::create (true, config, logger, nano::dev::network_params.work); + ASSERT_TRUE (opencl); + + // 0 threads, should add 1 for managing OpenCL + bool opencl_function_called = false; + nano::work_pool pool{ nano::dev::network_params.network, 0, std::chrono::nanoseconds (0), + [&opencl, &opencl_function_called] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { + opencl_function_called = true; + return opencl->generate_work (version_a, root_a, difficulty_a); + } }; + ASSERT_NE (nullptr, pool.opencl); + + nano::root root; + uint64_t difficulty (0xffff000000000000); + uint64_t difficulty_add (0x00000f0000000000); + for (auto i (0); i < 16; ++i) { - std::cout << "Device with OpenCL support not found. Skipping OpenCL test" << std::endl; + nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ()); + auto nonce_opt = pool.generate (nano::work_version::work_1, root, difficulty); + ASSERT_TRUE (nonce_opt.has_value ()); + auto nonce = nonce_opt.get (); + ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, nonce), difficulty); + difficulty += difficulty_add; } + ASSERT_TRUE (opencl_function_called); } +// repeat difficulty calculations until a difficulty in a certain range is found TEST (work, difficulty) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::root root (1); - uint64_t difficulty1 (0xff00000000000000); - uint64_t difficulty2 (0xfff0000000000000); - uint64_t difficulty3 (0xffff000000000000); - uint64_t result_difficulty1 (0); + const nano::root root (1); + uint64_t difficulty1 = 0xff00000000000000; + uint64_t difficulty2 = 0xfff0000000000000; + uint64_t difficulty3 = 0xffff000000000000; + + // find a difficulty between difficulty1 and difficulty2 + uint64_t result_difficulty1 = 0; do { auto work1 = *pool.generate (nano::work_version::work_1, root, difficulty1); result_difficulty1 = nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, work1); } while (result_difficulty1 > difficulty2); ASSERT_GT (result_difficulty1, difficulty1); + + // find a difficulty between difficulty2 and difficulty3 uint64_t result_difficulty2 (0); do { @@ -152,6 +159,7 @@ TEST (work, difficulty) ASSERT_GT (result_difficulty2, difficulty2); } +// check that the pow_rate_limiter of work_pool works, this test can fail occasionally TEST (work, eco_pow) { auto work_func = [] (std::promise & promise, std::chrono::nanoseconds interval) { diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index d56f55e8f7..c7029af764 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -21,6 +21,11 @@ add_library( ${platform_sources} asio.hpp asio.cpp + block_sideband.hpp + block_sideband.cpp + block_type.hpp + block_type.cpp + block_uniquer.hpp blockbuilders.hpp blockbuilders.cpp blocks.hpp @@ -50,11 +55,17 @@ add_library( lmdbconfig.cpp locks.hpp locks.cpp - logger_mt.hpp + logging.hpp + logging.cpp + logging_enums.hpp + logging_enums.cpp memory.hpp memory.cpp numbers.hpp numbers.cpp + object_stream.hpp + object_stream.cpp + object_stream_adapters.hpp observer_set.hpp optional_ptr.hpp processing_queue.hpp @@ -100,7 +111,6 @@ add_library( work.cpp) include_directories(${CMAKE_SOURCE_DIR}/submodules) -include_directories(${CMAKE_SOURCE_DIR}/submodules/cpptoml/include) include_directories( ${CMAKE_SOURCE_DIR}/submodules/nano-pow-server/deps/cpptoml/include) @@ -111,14 +121,15 @@ target_link_libraries( blake2 ${CRYPTOPP_LIBRARY} ${CMAKE_DL_LIBS} + fmt::fmt + spdlog::spdlog Boost::iostreams Boost::asio Boost::circular_buffer Boost::dll - Boost::log_setup - Boost::log Boost::multiprecision Boost::program_options + Boost::property_tree Boost::stacktrace) if(NANO_STACKTRACE_BACKTRACE) diff --git a/nano/lib/block_sideband.cpp b/nano/lib/block_sideband.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nano/lib/block_sideband.hpp b/nano/lib/block_sideband.hpp new file mode 100644 index 0000000000..871f9bfcfc --- /dev/null +++ b/nano/lib/block_sideband.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace nano +{ +class object_stream; +} + +namespace nano +{ +class block_details +{ + static_assert (std::is_same::type, uint8_t> (), "Epoch enum is not the proper type"); + static_assert (static_cast (nano::epoch::max) < (1 << 5), "Epoch max is too large for the sideband"); + +public: + block_details () = default; + block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a); + static constexpr size_t size () + { + return 1; + } + bool operator== (block_details const & other_a) const; + void serialize (nano::stream &) const; + bool deserialize (nano::stream &); + nano::epoch epoch{ nano::epoch::epoch_0 }; + bool is_send{ false }; + bool is_receive{ false }; + bool is_epoch{ false }; + +private: + uint8_t packed () const; + void unpack (uint8_t); + +public: // Logging + void operator() (nano::object_stream &) const; +}; + +std::string state_subtype (nano::block_details const); + +class block_sideband final +{ +public: + block_sideband () = default; + block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, nano::seconds_t const local_timestamp, nano::block_details const &, nano::epoch const source_epoch_a); + block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, nano::seconds_t const local_timestamp, nano::epoch const epoch_a, bool const is_send, bool const is_receive, bool const is_epoch, nano::epoch const source_epoch_a); + void serialize (nano::stream &, nano::block_type) const; + bool deserialize (nano::stream &, nano::block_type); + static size_t size (nano::block_type); + nano::block_hash successor{ 0 }; + nano::account account{}; + nano::amount balance{ 0 }; + uint64_t height{ 0 }; + uint64_t timestamp{ 0 }; + nano::block_details details; + nano::epoch source_epoch{ nano::epoch::epoch_0 }; + +public: // Logging + void operator() (nano::object_stream &) const; +}; +} // namespace nano diff --git a/nano/lib/block_type.cpp b/nano/lib/block_type.cpp new file mode 100644 index 0000000000..4afb9b0fdb --- /dev/null +++ b/nano/lib/block_type.cpp @@ -0,0 +1,13 @@ +#include + +#include + +std::string_view nano::to_string (nano::block_type type) +{ + return magic_enum::enum_name (type); +} + +void nano::serialize_block_type (nano::stream & stream, const nano::block_type & type) +{ + nano::write (stream, type); +} diff --git a/nano/lib/block_type.hpp b/nano/lib/block_type.hpp new file mode 100644 index 0000000000..020722e315 --- /dev/null +++ b/nano/lib/block_type.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include +#include + +namespace nano +{ +enum class block_type : uint8_t +{ + invalid = 0, + not_a_block = 1, + send = 2, + receive = 3, + open = 4, + change = 5, + state = 6 +}; + +std::string_view to_string (block_type); +/** + * Serialize block type as an 8-bit value + */ +void serialize_block_type (nano::stream &, nano::block_type const &); +} // namespace nano diff --git a/nano/lib/block_uniquer.hpp b/nano/lib/block_uniquer.hpp new file mode 100644 index 0000000000..d39bb3afc4 --- /dev/null +++ b/nano/lib/block_uniquer.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +namespace nano +{ +class block; +using block_uniquer = nano::uniquer; +} diff --git a/nano/lib/blockbuilders.cpp b/nano/lib/blockbuilders.cpp index edb5499d95..d8fa600f8f 100644 --- a/nano/lib/blockbuilders.cpp +++ b/nano/lib/blockbuilders.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include @@ -652,7 +655,7 @@ nano::receive_block_builder & nano::receive_block_builder::source_hex (std::stri } template -std::unique_ptr nano::abstract_builder::build () +std::shared_ptr nano::abstract_builder::build () { if (!ec) { @@ -663,7 +666,7 @@ std::unique_ptr nano::abstract_builder::build () } template -std::unique_ptr nano::abstract_builder::build (std::error_code & ec) +std::shared_ptr nano::abstract_builder::build (std::error_code & ec) { if (!this->ec) { @@ -673,18 +676,6 @@ std::unique_ptr nano::abstract_builder::build (st return std::move (block); } -template -std::shared_ptr nano::abstract_builder::build_shared () -{ - return std::move (build ()); -} - -template -std::shared_ptr nano::abstract_builder::build_shared (std::error_code & ec) -{ - return std::move (build (ec)); -} - template nano::abstract_builder & nano::abstract_builder::work (uint64_t work) { diff --git a/nano/lib/blockbuilders.hpp b/nano/lib/blockbuilders.hpp index d77a441f01..1471c9bb20 100644 --- a/nano/lib/blockbuilders.hpp +++ b/nano/lib/blockbuilders.hpp @@ -1,9 +1,18 @@ #pragma once -#include +#include #include +namespace nano +{ +class change_block; +class send_block; +class state_block; +class open_block; +class receive_block; +} + namespace nano { /** Flags to track builder state */ @@ -44,14 +53,10 @@ template class abstract_builder { public: - /** Returns the built block as a unique_ptr */ - std::unique_ptr build (); - /** Returns the built block as a unique_ptr. Any errors are placed in \p ec */ - std::unique_ptr build (std::error_code & ec); - /** Returns the built block as a shared_ptr */ - std::shared_ptr build_shared (); - /** Returns the built block as a shared_ptr. Any errors are placed in \p ec */ - std::shared_ptr build_shared (std::error_code & ec); + /** Returns the built block*/ + std::shared_ptr build (); + /** Returns the built block. Any errors are placed in \p ec */ + std::shared_ptr build (std::error_code & ec); /** Set work value */ abstract_builder & work (uint64_t work); /** Sign the block using the \p private_key and \p public_key */ diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index 15881b3e50..060681ac12 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -11,6 +11,13 @@ #include #include +#include + +size_t constexpr nano::send_block::size; +size_t constexpr nano::receive_block::size; +size_t constexpr nano::open_block::size; +size_t constexpr nano::change_block::size; +size_t constexpr nano::state_block::size; /** Compare blocks, first by type, then content. This is an optimization over dynamic_cast, which is very slow on some platforms. */ namespace @@ -44,6 +51,10 @@ void nano::block_memory_pool_purge () nano::purge_shared_ptr_singleton_pool_memory (); } +/* + * block + */ + std::string nano::block::to_json () const { std::string result; @@ -104,6 +115,53 @@ void nano::block::refresh () } } +bool nano::block::is_send () const noexcept +{ + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::send: + return true; + case nano::block_type::state: + return sideband ().details.is_send; + default: + return false; + } +} + +bool nano::block::is_receive () const noexcept +{ + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::receive: + case nano::block_type::open: + return true; + case nano::block_type::state: + return sideband ().details.is_receive; + default: + return false; + } +} + +bool nano::block::is_change () const noexcept +{ + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::change: + return true; + case nano::block_type::state: + if (link_field ().value ().is_zero ()) + { + return true; + } + return false; + default: + return false; + } +} + nano::block_hash const & nano::block::hash () const { if (!cached_hash.is_zero ()) @@ -150,47 +208,135 @@ bool nano::block::has_sideband () const return sideband_m.is_initialized (); } -nano::account const & nano::block::representative () const +std::optional nano::block::representative_field () const +{ + return std::nullopt; +} + +std::optional nano::block::source_field () const +{ + return std::nullopt; +} + +std::optional nano::block::destination_field () const +{ + return std::nullopt; +} + +std::optional nano::block::link_field () const +{ + return std::nullopt; +} + +nano::account nano::block::account () const noexcept +{ + release_assert (has_sideband ()); + switch (type ()) + { + case block_type::open: + case block_type::state: + return account_field ().value (); + case block_type::change: + case block_type::send: + case block_type::receive: + return sideband ().account; + default: + release_assert (false); + } +} + +nano::amount nano::block::balance () const noexcept { - static nano::account representative{}; - return representative; + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::open: + case nano::block_type::receive: + case nano::block_type::change: + return sideband ().balance; + case nano::block_type::send: + case nano::block_type::state: + return balance_field ().value (); + default: + release_assert (false); + } } -nano::block_hash const & nano::block::source () const +nano::account nano::block::destination () const noexcept { - static nano::block_hash source{ 0 }; - return source; + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::send: + return destination_field ().value (); + case nano::block_type::state: + release_assert (sideband ().details.is_send); + return link_field ().value ().as_account (); + default: + release_assert (false); + } } -nano::account const & nano::block::destination () const +nano::block_hash nano::block::source () const noexcept { - static nano::account destination{}; - return destination; + release_assert (has_sideband ()); + switch (type ()) + { + case nano::block_type::open: + case nano::block_type::receive: + return source_field ().value (); + case nano::block_type::state: + release_assert (sideband ().details.is_receive); + return link_field ().value ().as_block_hash (); + default: + release_assert (false); + } } -nano::link const & nano::block::link () const +// TODO - Remove comments below and fixup usages to not need to check .is_zero () +// std::optional nano::block::previous () const +nano::block_hash nano::block::previous () const noexcept { - static nano::link link{ 0 }; - return link; + std::optional result = previous_field (); + /* + if (result && result.value ().is_zero ()) + { + return std::nullopt; + } + return result;*/ + return result.value_or (0); } -nano::account const & nano::block::account () const +std::optional nano::block::account_field () const { - static nano::account account{}; - return account; + return std::nullopt; } nano::qualified_root nano::block::qualified_root () const { - return nano::qualified_root (root (), previous ()); + return { root (), previous () }; +} + +std::optional nano::block::balance_field () const +{ + return std::nullopt; } -nano::amount const & nano::block::balance () const +void nano::block::operator() (nano::object_stream & obs) const { - static nano::amount amount{ 0 }; - return amount; + obs.write ("type", type ()); + obs.write ("hash", hash ()); + + if (has_sideband ()) + { + obs.write ("sideband", sideband ()); + } } +/* + * send_block + */ + void nano::send_block::visit (nano::block_visitor & visitor_a) const { visitor_a.send_block (*this); @@ -441,12 +587,12 @@ bool nano::send_block::operator== (nano::send_block const & other_a) const return result; } -nano::block_hash const & nano::send_block::previous () const +std::optional nano::send_block::previous_field () const { return hashables.previous; } -nano::account const & nano::send_block::destination () const +std::optional nano::send_block::destination_field () const { return hashables.destination; } @@ -456,7 +602,7 @@ nano::root const & nano::send_block::root () const return hashables.previous; } -nano::amount const & nano::send_block::balance () const +std::optional nano::send_block::balance_field () const { return hashables.balance; } @@ -471,6 +617,21 @@ void nano::send_block::signature_set (nano::signature const & signature_a) signature = signature_a; } +void nano::send_block::operator() (nano::object_stream & obs) const +{ + nano::block::operator() (obs); // Write common data + + obs.write ("previous", hashables.previous); + obs.write ("destination", hashables.destination); + obs.write ("balance", hashables.balance); + obs.write ("signature", signature); + obs.write ("work", work); +} + +/* + * open_block + */ + nano::open_hashables::open_hashables (nano::block_hash const & source_a, nano::account const & representative_a, nano::account const & account_a) : source (source_a), representative (representative_a), @@ -596,13 +757,12 @@ void nano::open_block::block_work_set (uint64_t work_a) work = work_a; } -nano::block_hash const & nano::open_block::previous () const +std::optional nano::open_block::previous_field () const { - static nano::block_hash result{ 0 }; - return result; + return std::nullopt; } -nano::account const & nano::open_block::account () const +std::optional nano::open_block::account_field () const { return hashables.account; } @@ -648,7 +808,7 @@ void nano::open_block::serialize_json (boost::property_tree::ptree & tree) const { tree.put ("type", "open"); tree.put ("source", hashables.source.to_string ()); - tree.put ("representative", representative ().to_account ()); + tree.put ("representative", hashables.representative.to_account ()); tree.put ("account", hashables.account.to_account ()); std::string signature_l; signature.encode_hex (signature_l); @@ -722,7 +882,7 @@ bool nano::open_block::valid_predecessor (nano::block const & block_a) const return false; } -nano::block_hash const & nano::open_block::source () const +std::optional nano::open_block::source_field () const { return hashables.source; } @@ -732,7 +892,7 @@ nano::root const & nano::open_block::root () const return hashables.account; } -nano::account const & nano::open_block::representative () const +std::optional nano::open_block::representative_field () const { return hashables.representative; } @@ -747,6 +907,21 @@ void nano::open_block::signature_set (nano::signature const & signature_a) signature = signature_a; } +void nano::open_block::operator() (nano::object_stream & obs) const +{ + nano::block::operator() (obs); // Write common data + + obs.write ("source", hashables.source); + obs.write ("representative", hashables.representative); + obs.write ("account", hashables.account); + obs.write ("signature", signature); + obs.write ("work", work); +} + +/* + * change_block + */ + nano::change_hashables::change_hashables (nano::block_hash const & previous_a, nano::account const & representative_a) : previous (previous_a), representative (representative_a) @@ -853,7 +1028,7 @@ void nano::change_block::block_work_set (uint64_t work_a) work = work_a; } -nano::block_hash const & nano::change_block::previous () const +std::optional nano::change_block::previous_field () const { return hashables.previous; } @@ -897,7 +1072,7 @@ void nano::change_block::serialize_json (boost::property_tree::ptree & tree) con { tree.put ("type", "change"); tree.put ("previous", hashables.previous.to_string ()); - tree.put ("representative", representative ().to_account ()); + tree.put ("representative", hashables.representative.to_account ()); tree.put ("work", nano::to_string_hex (work)); std::string signature_l; signature.encode_hex (signature_l); @@ -983,7 +1158,7 @@ nano::root const & nano::change_block::root () const return hashables.previous; } -nano::account const & nano::change_block::representative () const +std::optional nano::change_block::representative_field () const { return hashables.representative; } @@ -998,6 +1173,20 @@ void nano::change_block::signature_set (nano::signature const & signature_a) signature = signature_a; } +void nano::change_block::operator() (nano::object_stream & obs) const +{ + nano::block::operator() (obs); // Write common data + + obs.write ("previous", hashables.previous); + obs.write ("representative", hashables.representative); + obs.write ("signature", signature); + obs.write ("work", work); +} + +/* + * state_block + */ + nano::state_hashables::state_hashables (nano::account const & account_a, nano::block_hash const & previous_a, nano::account const & representative_a, nano::amount const & balance_a, nano::link const & link_a) : account (account_a), previous (previous_a), @@ -1138,12 +1327,12 @@ void nano::state_block::block_work_set (uint64_t work_a) work = work_a; } -nano::block_hash const & nano::state_block::previous () const +std::optional nano::state_block::previous_field () const { return hashables.previous; } -nano::account const & nano::state_block::account () const +std::optional nano::state_block::account_field () const { return hashables.account; } @@ -1195,7 +1384,7 @@ void nano::state_block::serialize_json (boost::property_tree::ptree & tree) cons tree.put ("type", "state"); tree.put ("account", hashables.account.to_account ()); tree.put ("previous", hashables.previous.to_string ()); - tree.put ("representative", representative ().to_account ()); + tree.put ("representative", hashables.representative.to_account ()); tree.put ("balance", hashables.balance.to_string_dec ()); tree.put ("link", hashables.link.to_string ()); tree.put ("link_as_account", hashables.link.to_account ()); @@ -1293,17 +1482,17 @@ nano::root const & nano::state_block::root () const } } -nano::link const & nano::state_block::link () const +std::optional nano::state_block::link_field () const { return hashables.link; } -nano::account const & nano::state_block::representative () const +std::optional nano::state_block::representative_field () const { return hashables.representative; } -nano::amount const & nano::state_block::balance () const +std::optional nano::state_block::balance_field () const { return hashables.balance; } @@ -1318,6 +1507,23 @@ void nano::state_block::signature_set (nano::signature const & signature_a) signature = signature_a; } +void nano::state_block::operator() (nano::object_stream & obs) const +{ + nano::block::operator() (obs); // Write common data + + obs.write ("account", hashables.account); + obs.write ("previous", hashables.previous); + obs.write ("representative", hashables.representative); + obs.write ("balance", hashables.balance); + obs.write ("link", hashables.link); + obs.write ("signature", signature); + obs.write ("work", work); +} + +/* + * + */ + std::shared_ptr nano::deserialize_block_json (boost::property_tree::ptree const & tree_a, nano::block_uniquer * uniquer_a) { std::shared_ptr result; @@ -1362,11 +1568,6 @@ std::shared_ptr nano::deserialize_block_json (boost::property_tree: return result; } -void nano::serialize_block_type (nano::stream & stream, const nano::block_type & type) -{ - nano::write (stream, type); -} - void nano::serialize_block (nano::stream & stream_a, nano::block const & block_a) { nano::serialize_block_type (stream_a, block_a.type ()); @@ -1427,6 +1628,10 @@ std::shared_ptr nano::deserialize_block (nano::stream & stream_a, n return result; } +/* + * receive_block + */ + void nano::receive_block::visit (nano::block_visitor & visitor_a) const { visitor_a.receive_block (*this); @@ -1609,12 +1814,12 @@ bool nano::receive_block::valid_predecessor (nano::block const & block_a) const return result; } -nano::block_hash const & nano::receive_block::previous () const +std::optional nano::receive_block::previous_field () const { return hashables.previous; } -nano::block_hash const & nano::receive_block::source () const +std::optional nano::receive_block::source_field () const { return hashables.source; } @@ -1682,6 +1887,20 @@ void nano::receive_hashables::hash (blake2b_state & hash_a) const blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); } +void nano::receive_block::operator() (nano::object_stream & obs) const +{ + nano::block::operator() (obs); // Write common data + + obs.write ("previous", hashables.previous); + obs.write ("source", hashables.source); + obs.write ("signature", signature); + obs.write ("work", work); +} + +/* + * block_details + */ + nano::block_details::block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a) : epoch (epoch_a), is_send (is_send_a), is_receive (is_receive_a), is_epoch (is_epoch_a) { @@ -1733,6 +1952,14 @@ bool nano::block_details::deserialize (nano::stream & stream_a) return result; } +void nano::block_details::operator() (nano::object_stream & obs) const +{ + obs.write ("epoch", epoch); + obs.write ("is_send", is_send); + obs.write ("is_receive", is_receive); + obs.write ("is_epoch", is_epoch); +} + std::string nano::state_subtype (nano::block_details const details_a) { debug_assert (details_a.is_epoch + details_a.is_receive + details_a.is_send <= 1); @@ -1754,6 +1981,10 @@ std::string nano::state_subtype (nano::block_details const details_a) } } +/* + * block_sideband + */ + nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t const height_a, nano::seconds_t const timestamp_a, nano::block_details const & details_a, nano::epoch const source_epoch_a) : successor (successor_a), account (account_a), @@ -1864,3 +2095,14 @@ bool nano::block_sideband::deserialize (nano::stream & stream_a, nano::block_typ return result; } + +void nano::block_sideband::operator() (nano::object_stream & obs) const +{ + obs.write ("successor", successor); + obs.write ("account", account); + obs.write ("balance", balance); + obs.write ("height", height); + obs.write ("timestamp", timestamp); + obs.write ("source_epoch", source_epoch); + obs.write ("details", details); +} diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 5a9ab168bc..d6cca74374 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -1,78 +1,24 @@ #pragma once -#include +#include +#include +#include #include #include #include #include #include -#include -#include -#include -#include #include -#include +typedef struct blake2b_state__ blake2b_state; namespace nano { class block_visitor; class mutable_block_visitor; -enum class block_type : uint8_t -{ - invalid = 0, - not_a_block = 1, - send = 2, - receive = 3, - open = 4, - change = 5, - state = 6 -}; -class block_details -{ - static_assert (std::is_same::type, uint8_t> (), "Epoch enum is not the proper type"); - static_assert (static_cast (nano::epoch::max) < (1 << 5), "Epoch max is too large for the sideband"); - -public: - block_details () = default; - block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a); - static constexpr size_t size () - { - return 1; - } - bool operator== (block_details const & other_a) const; - void serialize (nano::stream &) const; - bool deserialize (nano::stream &); - nano::epoch epoch{ nano::epoch::epoch_0 }; - bool is_send{ false }; - bool is_receive{ false }; - bool is_epoch{ false }; - -private: - uint8_t packed () const; - void unpack (uint8_t); -}; - -std::string state_subtype (nano::block_details const); +class object_stream; -class block_sideband final -{ -public: - block_sideband () = default; - block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, nano::seconds_t const local_timestamp, nano::block_details const &, nano::epoch const source_epoch_a); - block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, nano::seconds_t const local_timestamp, nano::epoch const epoch_a, bool const is_send, bool const is_receive, bool const is_epoch, nano::epoch const source_epoch_a); - void serialize (nano::stream &, nano::block_type) const; - bool deserialize (nano::stream &, nano::block_type); - static size_t size (nano::block_type); - nano::block_hash successor{ 0 }; - nano::account account{}; - nano::amount balance{ 0 }; - uint64_t height{ 0 }; - uint64_t timestamp{ 0 }; - nano::block_details details; - nano::epoch source_epoch{ nano::epoch::epoch_0 }; -}; class block { public: @@ -87,21 +33,10 @@ class block virtual void hash (blake2b_state &) const = 0; virtual uint64_t block_work () const = 0; virtual void block_work_set (uint64_t) = 0; - virtual nano::account const & account () const; - // Previous block in account's chain, zero for open block - virtual nano::block_hash const & previous () const = 0; - // Source block for open/receive blocks, zero otherwise. - virtual nano::block_hash const & source () const; - // Destination account for send blocks, zero otherwise. - virtual nano::account const & destination () const; // Previous block or account number for open blocks virtual nano::root const & root () const = 0; // Qualified root value based on previous() and root() virtual nano::qualified_root qualified_root () const; - // Link field for state blocks, zero otherwise. - virtual nano::link const & link () const; - virtual nano::account const & representative () const; - virtual nano::amount const & balance () const; virtual void serialize (nano::stream &) const = 0; virtual void serialize_json (std::string &, bool = false) const = 0; virtual void serialize_json (boost::property_tree::ptree &) const = 0; @@ -117,6 +52,35 @@ class block virtual nano::work_version work_version () const; // If there are any changes to the hashables, call this to update the cached hash void refresh (); + bool is_send () const noexcept; + bool is_receive () const noexcept; + bool is_change () const noexcept; + +public: // Direct access to the block fields or nullopt if the block type does not have the specified field + // Returns account field or account from sideband + nano::account account () const noexcept; + // Account field for open/state blocks + virtual std::optional account_field () const; + // Returns the balance field or balance from sideband + nano::amount balance () const noexcept; + // Balance field for open/send/state blocks + virtual std::optional balance_field () const; + // Returns the destination account for send/state blocks that are sends + nano::account destination () const noexcept; + // Destination account for send blocks + virtual std::optional destination_field () const; + // Link field for state blocks + virtual std::optional link_field () const; + // Previous block if field exists or 0 + nano::block_hash previous () const noexcept; + // Previous block in chain if the field exists + virtual std::optional previous_field () const = 0; + // Representative field for open/change blocks + virtual std::optional representative_field () const; + // Returns the source block hash for open/receive/state blocks that are receives + nano::block_hash source () const noexcept; + // Source block for open/receive blocks + virtual std::optional source_field () const; protected: mutable nano::block_hash cached_hash{ 0 }; @@ -129,9 +93,10 @@ class block private: nano::block_hash generate_hash () const; -}; -using block_list_t = std::vector>; +public: // Logging + virtual void operator() (nano::object_stream &) const; +}; class send_hashables { @@ -146,6 +111,7 @@ class send_hashables nano::amount balance; static std::size_t constexpr size = sizeof (previous) + sizeof (destination) + sizeof (balance); }; + class send_block : public nano::block { public: @@ -158,10 +124,7 @@ class send_block : public nano::block void hash (blake2b_state &) const override; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::block_hash const & previous () const override; - nano::account const & destination () const override; nano::root const & root () const override; - nano::amount const & balance () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -179,7 +142,16 @@ class send_block : public nano::block nano::signature signature; uint64_t work; static std::size_t constexpr size = nano::send_hashables::size + sizeof (signature) + sizeof (work); + +public: // Send block fields + std::optional balance_field () const override; + std::optional destination_field () const override; + std::optional previous_field () const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; + class receive_hashables { public: @@ -192,6 +164,7 @@ class receive_hashables nano::block_hash source; static std::size_t constexpr size = sizeof (previous) + sizeof (source); }; + class receive_block : public nano::block { public: @@ -204,8 +177,6 @@ class receive_block : public nano::block void hash (blake2b_state &) const override; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::block_hash const & previous () const override; - nano::block_hash const & source () const override; nano::root const & root () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); @@ -224,7 +195,15 @@ class receive_block : public nano::block nano::signature signature; uint64_t work; static std::size_t constexpr size = nano::receive_hashables::size + sizeof (signature) + sizeof (work); + +public: // Receive block fields + std::optional previous_field () const override; + std::optional source_field () const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; + class open_hashables { public: @@ -238,6 +217,7 @@ class open_hashables nano::account account; static std::size_t constexpr size = sizeof (source) + sizeof (representative) + sizeof (account); }; + class open_block : public nano::block { public: @@ -251,11 +231,7 @@ class open_block : public nano::block void hash (blake2b_state &) const override; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::block_hash const & previous () const override; - nano::account const & account () const override; - nano::block_hash const & source () const override; nano::root const & root () const override; - nano::account const & representative () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -273,7 +249,17 @@ class open_block : public nano::block nano::signature signature; uint64_t work; static std::size_t constexpr size = nano::open_hashables::size + sizeof (signature) + sizeof (work); + +public: // Open block fields + std::optional account_field () const override; + std::optional previous_field () const override; + std::optional representative_field () const override; + std::optional source_field () const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; + class change_hashables { public: @@ -286,6 +272,7 @@ class change_hashables nano::account representative; static std::size_t constexpr size = sizeof (previous) + sizeof (representative); }; + class change_block : public nano::block { public: @@ -298,9 +285,7 @@ class change_block : public nano::block void hash (blake2b_state &) const override; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::block_hash const & previous () const override; nano::root const & root () const override; - nano::account const & representative () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -318,7 +303,15 @@ class change_block : public nano::block nano::signature signature; uint64_t work; static std::size_t constexpr size = nano::change_hashables::size + sizeof (signature) + sizeof (work); + +public: // Change block fields + std::optional previous_field () const override; + std::optional representative_field () const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; + class state_hashables { public: @@ -344,6 +337,7 @@ class state_hashables // Serialized size static std::size_t constexpr size = sizeof (account) + sizeof (previous) + sizeof (representative) + sizeof (balance) + sizeof (link); }; + class state_block : public nano::block { public: @@ -356,12 +350,7 @@ class state_block : public nano::block void hash (blake2b_state &) const override; uint64_t block_work () const override; void block_work_set (uint64_t) override; - nano::block_hash const & previous () const override; - nano::account const & account () const override; nano::root const & root () const override; - nano::link const & link () const override; - nano::account const & representative () const override; - nano::amount const & balance () const override; void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void serialize_json (std::string &, bool = false) const override; @@ -379,7 +368,18 @@ class state_block : public nano::block nano::signature signature; uint64_t work; static std::size_t constexpr size = nano::state_hashables::size + sizeof (signature) + sizeof (work); + +public: // State block fields + std::optional account_field () const override; + std::optional balance_field () const override; + std::optional link_field () const override; + std::optional previous_field () const override; + std::optional representative_field () const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; + class block_visitor { public: @@ -401,15 +401,9 @@ class mutable_block_visitor virtual ~mutable_block_visitor () = default; }; -using block_uniquer = nano::uniquer; - std::shared_ptr deserialize_block (nano::stream &); std::shared_ptr deserialize_block (nano::stream &, nano::block_type, nano::block_uniquer * = nullptr); std::shared_ptr deserialize_block_json (boost::property_tree::ptree const &, nano::block_uniquer * = nullptr); -/** - * Serialize block type as an 8-bit value - */ -void serialize_block_type (nano::stream &, nano::block_type const &); /** * Serialize a block prefixed with an 8-bit typecode */ diff --git a/nano/lib/config.cpp b/nano/lib/config.cpp index 13273e1096..1839d7412e 100644 --- a/nano/lib/config.cpp +++ b/nano/lib/config.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include @@ -355,3 +357,60 @@ uint32_t nano::test_scan_wallet_reps_delay () auto test_env = nano::get_env_or_default ("NANO_TEST_WALLET_SCAN_REPS_DELAY", "900000"); // 15 minutes by default return boost::lexical_cast (test_env); } + +std::string_view nano::to_string (nano::networks network) +{ + switch (network) + { + case nano::networks::invalid: + return "invalid"; + case nano::networks::nano_beta_network: + return "beta"; + case nano::networks::nano_dev_network: + return "dev"; + case nano::networks::nano_live_network: + return "live"; + case nano::networks::nano_test_network: + return "test"; + // default case intentionally omitted to cause warnings for unhandled enums + } + + return "n/a"; +} + +// Using std::cerr here, since logging may not be initialized yet +nano::tomlconfig nano::load_toml_file (const std::filesystem::path & config_filename, const std::filesystem::path & data_path, const std::vector & config_overrides) +{ + std::stringstream config_overrides_stream; + for (auto const & entry : config_overrides) + { + config_overrides_stream << entry << std::endl; + } + config_overrides_stream << std::endl; + + // Make sure we don't create an empty toml file if it doesn't exist. Running without a toml file is the default. + auto toml_config_path = data_path / config_filename; + if (std::filesystem::exists (toml_config_path)) + { + nano::tomlconfig toml; + auto error = toml.read (config_overrides_stream, toml_config_path); + if (error) + { + throw std::runtime_error (error.get_message ()); + } + std::cerr << "Config file `" << config_filename.string () << "` loaded from node data directory: " << toml_config_path.string () << std::endl; + return toml; + } + else + { + // If no config was found, return an empty config with overrides applied + nano::tomlconfig toml; + auto error = toml.read (config_overrides_stream); + if (error) + { + throw std::runtime_error (error.get_message ()); + } + std::cerr << "Config file `" << config_filename.string () << "` not found, using default configuration" << std::endl; + return toml; + } +} diff --git a/nano/lib/config.hpp b/nano/lib/config.hpp index db8ef89752..3cedf420f1 100644 --- a/nano/lib/config.hpp +++ b/nano/lib/config.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -127,6 +129,8 @@ enum class networks : uint16_t nano_test_network = 0x5258, // 'R', 'X' }; +std::string_view to_string (nano::networks); + enum class work_version { unspecified, @@ -198,6 +202,7 @@ class network_constants default_websocket_port (47000), aec_loop_interval_ms (300), // Update AEC ~3 times per second cleanup_period (default_cleanup_period), + merge_period (std::chrono::milliseconds (250)), keepalive_period (std::chrono::seconds (15)), idle_timeout (default_cleanup_period * 2), silent_connection_tolerance_time (std::chrono::seconds (120)), @@ -207,7 +212,8 @@ class network_constants max_peers_per_subnetwork (default_max_peers_per_ip * 4), ipv6_subnetwork_prefix_for_limiting (64), // Equivalent to network prefix /64. peer_dump_interval (std::chrono::seconds (5 * 60)), - vote_broadcast_interval (15 * 1000) + vote_broadcast_interval (15 * 1000), + block_broadcast_interval (150 * 1000) { if (is_live_network ()) { @@ -234,17 +240,21 @@ class network_constants { aec_loop_interval_ms = 20; cleanup_period = std::chrono::seconds (1); + merge_period = std::chrono::milliseconds (10); keepalive_period = std::chrono::seconds (1); idle_timeout = cleanup_period * 15; max_peers_per_ip = 20; max_peers_per_subnetwork = max_peers_per_ip * 4; peer_dump_interval = std::chrono::seconds (1); - vote_broadcast_interval = 500; + vote_broadcast_interval = 500ms; + block_broadcast_interval = 500ms; telemetry_request_cooldown = 500ms; telemetry_cache_cutoff = 2000ms; telemetry_request_interval = 500ms; telemetry_broadcast_interval = 500ms; optimistic_activation_delay = 2s; + rep_crawler_normal_interval = 500ms; + rep_crawler_warmup_interval = 500ms; } } @@ -271,6 +281,8 @@ class network_constants { return cleanup_period * 5; } + /** How often to connect to other peers */ + std::chrono::milliseconds merge_period; /** How often to send keepalive messages */ std::chrono::seconds keepalive_period; /** Default maximum idle time for a socket before it's automatically closed */ @@ -284,8 +296,10 @@ class network_constants size_t max_peers_per_subnetwork; size_t ipv6_subnetwork_prefix_for_limiting; std::chrono::seconds peer_dump_interval; - /** Time to wait before vote rebroadcasts for active elections (milliseconds) */ - uint64_t vote_broadcast_interval; + + /** Time to wait before rebroadcasts for active elections */ + std::chrono::milliseconds vote_broadcast_interval; + std::chrono::milliseconds block_broadcast_interval; /** We do not reply to telemetry requests made within cooldown period */ std::chrono::milliseconds telemetry_request_cooldown{ 1000 * 15 }; @@ -299,6 +313,9 @@ class network_constants /** How much to delay activation of optimistic elections to avoid interfering with election scheduler */ std::chrono::seconds optimistic_activation_delay{ 30 }; + std::chrono::milliseconds rep_crawler_normal_interval{ 1000 * 7 }; + std::chrono::milliseconds rep_crawler_warmup_interval{ 1000 * 3 }; + /** Returns the network this object contains values for */ nano::networks network () const { @@ -404,4 +421,28 @@ bool is_sanitizer_build (); /** Set the active network to the dev network */ void force_nano_dev_network (); + +/** + * Attempt to read a configuration file from specified directory. Returns empty tomlconfig if nothing is found. + * @throws std::runtime_error with error code if the file or overrides are not valid toml + */ +nano::tomlconfig load_toml_file (const std::filesystem::path & config_filename, const std::filesystem::path & data_path, const std::vector & config_overrides); + +/** + * Attempt to read a configuration file from specified directory. Returns fallback config if nothing is found. + * @throws std::runtime_error with error code if the file or overrides are not valid toml or deserialization fails + */ +template +T load_config_file (T fallback, const std::filesystem::path & config_filename, const std::filesystem::path & data_path, const std::vector & config_overrides) +{ + auto toml = load_toml_file (config_filename, data_path, config_overrides); + + T config = fallback; + auto error = config.deserialize_toml (toml); + if (error) + { + throw std::runtime_error (error.get_message ()); + } + return config; +} } diff --git a/nano/lib/errors.cpp b/nano/lib/errors.cpp index 822722be62..ffcb10a82b 100644 --- a/nano/lib/errors.cpp +++ b/nano/lib/errors.cpp @@ -373,9 +373,9 @@ nano::error::operator std::string () const } /** - * Get error message, or an empty string if there's no error. If a custom error message is set, - * that will be returned, otherwise the error_code#message() is returned. - */ + * Get error message, or an empty string if there's no error. If a custom error message is set, + * that will be returned, otherwise the error_code#message() is returned. + */ std::string nano::error::get_message () const { std::string res = message; diff --git a/nano/lib/id_dispenser.hpp b/nano/lib/id_dispenser.hpp index 4b0cc53fe5..91aa651a17 100644 --- a/nano/lib/id_dispenser.hpp +++ b/nano/lib/id_dispenser.hpp @@ -59,4 +59,17 @@ class id_dispenser return dist; } }; + +inline id_dispenser & id_gen () +{ + static id_dispenser id_gen; + return id_gen; +} + +using id_t = id_dispenser::id_t; + +inline id_t next_id () +{ + return id_gen ().next_id (); +} } \ No newline at end of file diff --git a/nano/lib/ipc_client.hpp b/nano/lib/ipc_client.hpp index b3f5f93e1a..b0e2277fc3 100644 --- a/nano/lib/ipc_client.hpp +++ b/nano/lib/ipc_client.hpp @@ -84,7 +84,7 @@ namespace ipc } /** - * Returns a buffer with an IPC preamble for the given \p encoding_a followed by the payload. Depending on encoding, + * Returns a buffer with an IPC preamble for the given \p encoding_a followed by the payload. Depending on encoding, * the buffer may contain a payload length or end sentinel. */ nano::shared_const_buffer prepare_request (nano::ipc::payload_encoding encoding_a, std::string const & payload_a); diff --git a/nano/lib/jsonconfig.cpp b/nano/lib/jsonconfig.cpp index fb5a857d25..74523154c2 100644 --- a/nano/lib/jsonconfig.cpp +++ b/nano/lib/jsonconfig.cpp @@ -21,7 +21,7 @@ nano::jsonconfig::jsonconfig (boost::property_tree::ptree & tree_a, std::shared_ } /** - * Reads a json object from the stream + * Reads a json object from the stream * @return nano::error&, including a descriptive error message if the config file is malformed. */ nano::error & nano::jsonconfig::read (std::filesystem::path const & path_a) diff --git a/nano/lib/locks.cpp b/nano/lib/locks.cpp index 56a018b13d..231ef13c35 100644 --- a/nano/lib/locks.cpp +++ b/nano/lib/locks.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -250,8 +251,6 @@ char const * nano::mutex_identifier (mutexes mutex) { case mutexes::active: return "active"; - case mutexes::block_arrival: - return "block_arrival"; case mutexes::block_processor: return "block_processor"; case mutexes::block_uniquer: diff --git a/nano/lib/locks.hpp b/nano/lib/locks.hpp index cb490e455c..1bbe0a7fa1 100644 --- a/nano/lib/locks.hpp +++ b/nano/lib/locks.hpp @@ -20,7 +20,6 @@ bool any_filters_registered (); enum class mutexes { active, - block_arrival, block_processor, block_uniquer, blockstore_cache, @@ -179,7 +178,7 @@ class unique_lock final }; /** Assumes std implementations of std::condition_variable never actually call nano::unique_lock::lock/unlock, - but instead use OS intrinsics with the mutex handle directly. Due to this we also do not account for any + but instead use OS intrinsics with the mutex handle directly. Due to this we also do not account for any time the condition variable is blocked on another holder of the mutex. */ class condition_variable final { @@ -283,7 +282,7 @@ class locked owner->mutex.unlock (); } - T * operator-> () + T * operator->() { return &owner->obj; } @@ -301,7 +300,7 @@ class locked locked * owner{ nullptr }; }; - scoped_lock operator-> () + scoped_lock operator->() { return scoped_lock (this); } diff --git a/nano/lib/logger_mt.hpp b/nano/lib/logger_mt.hpp deleted file mode 100644 index 9afd47842a..0000000000 --- a/nano/lib/logger_mt.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -#include -#include -#include - -namespace nano -{ -enum class severity_level -{ - normal = 0, - error -}; -} - -// Attribute value tag type -struct severity_tag; - -inline boost::log::formatting_ostream & operator<< (boost::log::formatting_ostream & strm, boost::log::to_log_manip const & manip) -{ - // Needs to match order in the severity_level enum - static std::array strings = { - "", - "Error: " - }; - - nano::severity_level level = manip.get (); - debug_assert (static_cast (level) < strings.size ()); - strm << strings[static_cast (level)]; - return strm; -} - -namespace nano -{ -// A wrapper around a boost logger object to allow minimum -// time spaced output to prevent logging happening too quickly. -class logger_mt -{ -private: - void add_to_stream (boost::log::record_ostream & stream) - { - } - - template - void add_to_stream (boost::log::record_ostream & stream, const LogItem & first_log_item, LogItems &&... remainder_log_items) - { - stream << first_log_item; - add_to_stream (stream, remainder_log_items...); - } - - template - void output (nano::severity_level severity_level, LogItems &&... log_items) - { - boost::log::record rec = boost_logger_mt.open_record (boost::log::keywords::severity = severity_level); - if (rec) - { - boost::log::record_ostream strm (rec); - add_to_stream (strm, std::forward (log_items)...); - strm.flush (); - boost_logger_mt.push_record (std::move (rec)); - } - } - -public: - logger_mt () = default; - - /** - * @param min_log_delta_a The minimum time between successive output - */ - explicit logger_mt (std::chrono::milliseconds const & min_log_delta_a) : - min_log_delta (min_log_delta_a) - { - } - - /* - * @param log_items A collection of objects with overloaded operator<< to be output to the log file - * @params severity_level The severity level that this log message should have. - */ - template - void always_log (nano::severity_level severity_level, LogItems &&... log_items) - { - output (severity_level, std::forward (log_items)...); - } - - /* - * @param log_items A collection of objects with overloaded operator<< to be output to the log file. - */ - template - void always_log (LogItems &&... log_items) - { - always_log (nano::severity_level::normal, std::forward (log_items)...); - } - - /* - * @param log_items Output to the log file if the last write was over min_log_delta time ago. - * @params severity_level The severity level that this log message should have. - * @return true if nothing was logged - */ - template - bool try_log (nano::severity_level severity_level, LogItems &&... log_items) - { - auto error (true); - auto time_now = std::chrono::steady_clock::now (); - nano::unique_lock lk (last_log_time_mutex); - if (((time_now - last_log_time) > min_log_delta) || last_log_time == std::chrono::steady_clock::time_point{}) - { - last_log_time = time_now; - lk.unlock (); - output (severity_level, std::forward (log_items)...); - error = false; - } - return error; - } - - /* - * @param log_items Output to the log file if the last write was over min_log_delta time ago. - * @return true if nothing was logged - */ - template - bool try_log (LogItems &&... log_items) - { - return try_log (nano::severity_level::normal, std::forward (log_items)...); - } - - std::chrono::milliseconds min_log_delta{ 0 }; - -private: - nano::mutex last_log_time_mutex; - std::chrono::steady_clock::time_point last_log_time; - boost::log::sources::severity_logger_mt boost_logger_mt; -}; -} diff --git a/nano/lib/logging.cpp b/nano/lib/logging.cpp new file mode 100644 index 0000000000..7f6a6bd35a --- /dev/null +++ b/nano/lib/logging.cpp @@ -0,0 +1,592 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +nano::logger & nano::default_logger () +{ + static nano::logger logger{ "default" }; + return logger; +} + +/* + * logger + */ + +bool nano::logger::global_initialized{ false }; +nano::log_config nano::logger::global_config{}; +std::vector nano::logger::global_sinks{}; +nano::object_stream_config nano::logger::global_tracing_config{}; + +// By default, use only the tag as the logger name, since only one node is running in the process +std::function nano::logger::global_name_formatter{ [] (nano::log::logger_id logger_id, std::string identifier) { + return to_string (logger_id); +} }; + +void nano::logger::initialize (nano::log_config fallback, std::optional data_path, std::vector const & config_overrides) +{ + // Only load log config from file if data_path is available (i.e. not running in cli mode) + nano::log_config config = data_path ? nano::load_log_config (fallback, *data_path, config_overrides) : fallback; + initialize_common (config, data_path); + global_initialized = true; +} + +// Custom log formatter flags +namespace +{ +/// Takes a qualified identifier in the form `node_identifier::tag` and splits it into a pair of `identifier` and `tag` +/// It is a limitation of spldlog that we cannot attach additional data to the logger, so we have to encode the node identifier in the logger name +/// @returns +std::pair split_qualified_identifier (std::string_view qualified_identifier) +{ + auto pos = qualified_identifier.find ("::"); + debug_assert (pos != std::string_view::npos); // This should never happen, since the default logger name formatter always adds the tag + if (pos == std::string_view::npos) + { + return { std::string_view{}, qualified_identifier }; + } + else + { + return { qualified_identifier.substr (0, pos), qualified_identifier.substr (pos + 2) }; + } +} + +class identifier_formatter_flag : public spdlog::custom_flag_formatter +{ +public: + void format (const spdlog::details::log_msg & msg, const std::tm & tm, spdlog::memory_buf_t & dest) override + { + // Extract identifier and tag from logger name + auto [identifier, tag] = split_qualified_identifier (std::string_view (msg.logger_name.data (), msg.logger_name.size ())); + dest.append (identifier.data (), identifier.data () + identifier.size ()); + } + + std::unique_ptr clone () const override + { + return spdlog::details::make_unique (); + } +}; + +class tag_formatter_flag : public spdlog::custom_flag_formatter +{ +public: + void format (const spdlog::details::log_msg & msg, const std::tm & tm, spdlog::memory_buf_t & dest) override + { + // Extract identifier and tag from logger name + auto [identifier, tag] = split_qualified_identifier (std::string_view (msg.logger_name.data (), msg.logger_name.size ())); + dest.append (tag.data (), tag.data () + tag.size ()); + } + + std::unique_ptr clone () const override + { + return spdlog::details::make_unique (); + } +}; +} + +void nano::logger::initialize_for_tests (nano::log_config fallback) +{ + auto config = nano::load_log_config (std::move (fallback), /* load log config from current workdir */ std::filesystem::current_path ()); + initialize_common (config, /* store log file in current workdir */ std::filesystem::current_path ()); + + // Use tag and identifier as the logger name, since multiple nodes may be running in the same process + global_name_formatter = [] (nano::log::logger_id logger_id, std::string identifier) { + return fmt::format ("{}::{}", identifier, to_string (logger_id)); + }; + + // Setup formatter to include information about node identifier `[%i]` and tag `[%n]` + auto formatter = std::make_unique (); + formatter->add_flag ('i'); + formatter->add_flag ('n'); + formatter->set_pattern ("[%Y-%m-%d %H:%M:%S.%e] [%i] [%n] [%l] %v"); + + for (auto & sink : global_sinks) + { + sink->set_formatter (formatter->clone ()); + } + + global_initialized = true; +} + +// Using std::cerr here, since logging may not be initialized yet +void nano::logger::initialize_common (nano::log_config const & config, std::optional data_path) +{ + global_config = config; + + spdlog::set_automatic_registration (false); + spdlog::set_level (to_spdlog_level (config.default_level)); + + global_sinks.clear (); + + // Console setup + if (config.console.enable) + { + if (!config.console.to_cerr) + { + // Only use colors if not writing to cerr + if (config.console.colors) + { + auto console_sink = std::make_shared (); + global_sinks.push_back (console_sink); + } + else + { + auto console_sink = std::make_shared (); + global_sinks.push_back (console_sink); + } + } + else + { + if (config.console.colors) + { + std::cerr << "WARNING: Logging to cerr is enabled, console colors will be disabled" << std::endl; + } + + auto cerr_sink = std::make_shared (); + global_sinks.push_back (cerr_sink); + } + } + + // File setup + if (config.file.enable) + { + // In cases where data_path is not available, file logging should always be disabled + release_assert (data_path); + + auto now = std::chrono::system_clock::now (); + auto time = std::chrono::system_clock::to_time_t (now); + + auto filename = fmt::format ("log_{:%Y-%m-%d_%H-%M}-{:%S}", fmt::localtime (time), now.time_since_epoch ()); + std::replace (filename.begin (), filename.end (), '.', '_'); // Replace millisecond dot separator with underscore + + std::filesystem::path log_path{ data_path.value () / "log" / (filename + ".log") }; + log_path = std::filesystem::absolute (log_path); + + std::cerr << "Logging to file: " << log_path.string () << std::endl; + + // If either max_size or rotation_count is 0, then disable file rotation + if (config.file.max_size == 0 || config.file.rotation_count == 0) + { + std::cerr << "WARNING: Log file rotation is disabled, log file size may grow without bound" << std::endl; + + auto file_sink = std::make_shared (log_path.string (), true); + global_sinks.push_back (file_sink); + } + else + { + auto file_sink = std::make_shared (log_path.string (), config.file.max_size, config.file.rotation_count); + global_sinks.push_back (file_sink); + } + } + + // Tracing setup + switch (config.tracing_format) + { + case nano::log::tracing_format::standard: + global_tracing_config = nano::object_stream_config::default_config (); + break; + case nano::log::tracing_format::json: + global_tracing_config = nano::object_stream_config::json_config (); + break; + } +} + +void nano::logger::flush () +{ + for (auto & sink : global_sinks) + { + sink->flush (); + } +} + +/* + * logger + */ + +nano::logger::logger (std::string identifier) : + identifier{ std::move (identifier) } +{ + release_assert (global_initialized, "logging should be initialized before creating a logger"); +} + +nano::logger::~logger () +{ + flush (); +} + +spdlog::logger & nano::logger::get_logger (nano::log::type type, nano::log::detail detail) +{ + // This is a two-step process to avoid exclusively locking the mutex in the common case + { + std::shared_lock lock{ mutex }; + + if (auto it = spd_loggers.find ({ type, detail }); it != spd_loggers.end ()) + { + return *it->second; + } + } + // Not found, create a new logger + { + std::unique_lock lock{ mutex }; + + auto [it, inserted] = spd_loggers.emplace (std::make_pair (type, detail), make_logger ({ type, detail })); + return *it->second; + } +} + +std::shared_ptr nano::logger::make_logger (nano::log::logger_id logger_id) +{ + auto const & config = global_config; + auto const & sinks = global_sinks; + + auto name = global_name_formatter (logger_id, identifier); + auto spd_logger = std::make_shared (name, sinks.begin (), sinks.end ()); + + spd_logger->set_level (to_spdlog_level (find_level (logger_id))); + spd_logger->flush_on (to_spdlog_level (config.flush_level)); + + return spd_logger; +} + +nano::log::level nano::logger::find_level (nano::log::logger_id logger_id) const +{ + auto const & config = global_config; + auto const & [type, detail] = logger_id; + + // Check for a specific level for this logger + if (auto it = config.levels.find (logger_id); it != config.levels.end ()) + { + return it->second; + } + // Check for a default level for this logger type + if (auto it = config.levels.find ({ type, nano::log::detail::all }); it != config.levels.end ()) + { + return it->second; + } + // Use the default level + return config.default_level; +} + +spdlog::level::level_enum nano::logger::to_spdlog_level (nano::log::level level) +{ + switch (level) + { + case nano::log::level::off: + return spdlog::level::off; + case nano::log::level::critical: + return spdlog::level::critical; + case nano::log::level::error: + return spdlog::level::err; + case nano::log::level::warn: + return spdlog::level::warn; + case nano::log::level::info: + return spdlog::level::info; + case nano::log::level::debug: + return spdlog::level::debug; + case nano::log::level::trace: + return spdlog::level::trace; + } + debug_assert (false, "Invalid log level"); + return spdlog::level::off; +} + +/* + * logging config presets + */ + +nano::log_config nano::log_config::cli_default () +{ + log_config config{}; + config.default_level = nano::log::level::critical; + config.console.colors = false; // to avoid printing warning about cerr and colors + config.console.to_cerr = true; // Use cerr to avoid interference with CLI output that goes to stdout + config.file.enable = false; + return config; +} + +nano::log_config nano::log_config::daemon_default () +{ + log_config config{}; + config.default_level = nano::log::level::info; + return config; +} + +nano::log_config nano::log_config::tests_default () +{ + log_config config{}; + config.default_level = nano::log::level::off; + config.file.enable = false; + return config; +} + +nano::log_config nano::log_config::sample_config () +{ + log_config config{}; + config.default_level = nano::log::level::info; + config.levels = default_levels (nano::log::level::info); // Populate with default levels + return config; +} + +/* + * logging config + */ + +nano::error nano::log_config::serialize_toml (nano::tomlconfig & toml) const +{ + nano::tomlconfig config_toml; + serialize (config_toml); + toml.put_child ("log", config_toml); + + return toml.get_error (); +} + +nano::error nano::log_config::deserialize_toml (nano::tomlconfig & toml) +{ + try + { + auto logging_l = toml.get_optional_child ("log"); + if (logging_l) + { + deserialize (*logging_l); + } + } + catch (std::invalid_argument const & ex) + { + toml.get_error ().set (ex.what ()); + } + + return toml.get_error (); +} + +void nano::log_config::serialize (nano::tomlconfig & toml) const +{ + toml.put ("default_level", std::string{ to_string (default_level) }); + + nano::tomlconfig console_config; + console_config.put ("enable", console.enable); + console_config.put ("to_cerr", console.to_cerr); + console_config.put ("colors", console.colors); + toml.put_child ("console", console_config); + + nano::tomlconfig file_config; + file_config.put ("enable", file.enable); + file_config.put ("max_size", file.max_size); + file_config.put ("rotation_count", file.rotation_count); + toml.put_child ("file", file_config); + + nano::tomlconfig levels_config; + for (auto const & [logger_id, level] : levels) + { + auto logger_name = to_string (logger_id.first); + levels_config.put (std::string{ logger_name }, std::string{ to_string (level) }); + } + toml.put_child ("levels", levels_config); +} + +void nano::log_config::deserialize (nano::tomlconfig & toml) +{ + if (toml.has_key ("default_level")) + { + auto default_level_l = toml.get ("default_level"); + default_level = nano::log::parse_level (default_level_l); + } + + if (toml.has_key ("console")) + { + auto console_config = toml.get_required_child ("console"); + console_config.get ("enable", console.enable); + console_config.get ("to_cerr", console.to_cerr); + console_config.get ("colors", console.colors); + } + + if (toml.has_key ("file")) + { + auto file_config = toml.get_required_child ("file"); + file_config.get ("enable", file.enable); + file_config.get ("max_size", file.max_size); + file_config.get ("rotation_count", file.rotation_count); + } + + if (toml.has_key ("levels")) + { + auto levels_config = toml.get_required_child ("levels"); + for (auto & level : levels_config.get_values ()) + { + try + { + auto & [name_str, level_str] = level; + auto logger_level = nano::log::parse_level (level_str); + auto logger_id = nano::log::parse_logger_id (name_str); + + levels[logger_id] = logger_level; + } + catch (std::invalid_argument const & ex) + { + // Ignore but warn about invalid logger names + std::cerr << "Problem processing log config: " << ex.what () << std::endl; + } + } + } +} + +std::map nano::log_config::default_levels (nano::log::level default_level) +{ + std::map result; + for (auto const & type : nano::log::all_types ()) + { + result.emplace (std::make_pair (type, nano::log::detail::all), default_level); + } + return result; +} + +/* + * config loading + */ + +// Using std::cerr here, since logging may not be initialized yet +nano::log_config nano::load_log_config (nano::log_config fallback, const std::filesystem::path & data_path, const std::vector & config_overrides) +{ + const std::string config_filename = "config-log.toml"; + try + { + auto config = nano::load_config_file (fallback, config_filename, data_path, config_overrides); + + // Parse default log level from environment variable, e.g. "NANO_LOG=debug" + auto env_level = nano::get_env ("NANO_LOG"); + if (env_level) + { + try + { + auto level = nano::log::parse_level (*env_level); + config.default_level = level; + + std::cerr << "Using default log level from NANO_LOG environment variable: " << to_string (level) << std::endl; + } + catch (std::invalid_argument const & ex) + { + std::cerr << "Invalid log level from NANO_LOG environment variable: " << ex.what () << std::endl; + } + } + + // Parse per logger levels from environment variable, e.g. "NANO_LOG_LEVELS=ledger=debug,node=trace" + auto env_levels = nano::get_env ("NANO_LOG_LEVELS"); + if (env_levels) + { + std::map levels; + for (auto const & env_level_str : nano::util::split (*env_levels, ",")) + { + try + { + // Split 'logger_name=level' into a pair of 'logger_name' and 'level' + auto arr = nano::util::split (env_level_str, "="); + if (arr.size () != 2) + { + throw std::invalid_argument ("Invalid entry: " + env_level_str); + } + + auto name_str = arr[0]; + auto level_str = arr[1]; + + auto logger_id = nano::log::parse_logger_id (name_str); + auto logger_level = nano::log::parse_level (level_str); + + levels[logger_id] = logger_level; + + std::cerr << "Using logger log level from NANO_LOG_LEVELS environment variable: " << to_string (logger_id) << "=" << to_string (logger_level) << std::endl; + } + catch (std::invalid_argument const & ex) + { + std::cerr << "Invalid log level from NANO_LOG_LEVELS environment variable: " << ex.what () << std::endl; + } + } + + // Merge with existing levels + for (auto const & [logger_id, level] : levels) + { + config.levels[logger_id] = level; + } + } + + auto env_tracing_format = nano::get_env ("NANO_TRACE_FORMAT"); + if (env_tracing_format) + { + try + { + auto tracing_format = nano::log::parse_tracing_format (*env_tracing_format); + config.tracing_format = tracing_format; + + std::cerr << "Using trace format from NANO_TRACE_FORMAT environment variable: " << to_string (tracing_format) << std::endl; + } + catch (std::invalid_argument const & ex) + { + std::cerr << "Invalid trace format from NANO_TRACE_FORMAT environment variable: " << ex.what () << std::endl; + } + } + + auto tracing_configured = [&] () { + if (config.default_level == nano::log::level::trace) + { + return true; + } + for (auto const & [logger_id, level] : config.levels) + { + if (level == nano::log::level::trace) + { + return true; + } + } + return false; + }; + + if (tracing_configured () && !is_tracing_enabled ()) + { + std::cerr << "WARNING: Tracing is not enabled in this build, but log level is set to trace" << std::endl; + } + + return config; + } + catch (std::runtime_error const & ex) + { + std::cerr << "Unable to load log config. Using defaults. Error: " << ex.what () << std::endl; + } + return fallback; +} + +std::string nano::log::to_string (nano::log::logger_id logger_id) +{ + auto const & [type, detail] = logger_id; + if (detail == nano::log::detail::all) + { + return fmt::format ("{}", to_string (type)); + } + else + { + return fmt::format ("{}::{}", to_string (type), to_string (detail)); + } +} + +/** + * Parse `logger_name[:logger_detail]` into a pair of `log::type` and `log::detail` + * @throw std::invalid_argument if `logger_name` or `logger_detail` are invalid + */ +nano::log::logger_id nano::log::parse_logger_id (const std::string & logger_name) +{ + auto parts = nano::util::split (logger_name, "::"); + if (parts.size () == 1) + { + return { nano::log::parse_type (parts[0]), nano::log::detail::all }; + } + if (parts.size () == 2) + { + return { nano::log::parse_type (parts[0]), nano::log::parse_detail (parts[1]) }; + } + throw std::invalid_argument ("Invalid logger name: " + logger_name); +} \ No newline at end of file diff --git a/nano/lib/logging.hpp b/nano/lib/logging.hpp new file mode 100644 index 0000000000..14e6e2fc3a --- /dev/null +++ b/nano/lib/logging.hpp @@ -0,0 +1,214 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace nano::log +{ +template +struct arg +{ + std::string_view name; + T const & value; + + arg (std::string_view name_a, T const & value_a) : + name{ name_a }, + value{ value_a } + { + } +}; + +using logger_id = std::pair; + +std::string to_string (logger_id); +logger_id parse_logger_id (std::string const &); + +template +auto microseconds (std::chrono::time_point time) +{ + return std::chrono::duration_cast (time.time_since_epoch ()).count (); +} +} + +namespace nano +{ +consteval bool is_tracing_enabled () +{ +#ifdef NANO_TRACING + return true; +#else + return false; +#endif +} + +class log_config final +{ +public: + nano::error serialize_toml (nano::tomlconfig &) const; + nano::error deserialize_toml (nano::tomlconfig &); + +private: + void serialize (nano::tomlconfig &) const; + void deserialize (nano::tomlconfig &); + +public: + nano::log::level default_level{ nano::log::level::info }; + nano::log::level flush_level{ nano::log::level::error }; + + std::map levels; + + struct console_config + { + bool enable{ true }; + bool colors{ true }; + bool to_cerr{ false }; + }; + + struct file_config + { + bool enable{ true }; + std::size_t max_size{ 32 * 1024 * 1024 }; + std::size_t rotation_count{ 4 }; + }; + + console_config console; + file_config file; + + nano::log::tracing_format tracing_format{ nano::log::tracing_format::standard }; + +public: // Predefined defaults + static log_config cli_default (); + static log_config daemon_default (); + static log_config tests_default (); + static log_config sample_config (); // For auto-generated sample config files + +private: + /// Returns placeholder log levels for all loggers + static std::map default_levels (nano::log::level); +}; + +nano::log_config load_log_config (nano::log_config fallback, std::filesystem::path const & data_path, std::vector const & config_overrides = {}); + +class logger final +{ +public: + explicit logger (std::string identifier = ""); + ~logger (); + + // Disallow copies + logger (logger const &) = delete; + +public: + static void initialize (nano::log_config fallback, std::optional data_path = std::nullopt, std::vector const & config_overrides = {}); + static void initialize_for_tests (nano::log_config fallback); + static void flush (); + +private: + static bool global_initialized; + static nano::log_config global_config; + static std::vector global_sinks; + static std::function global_name_formatter; + static nano::object_stream_config global_tracing_config; + + static void initialize_common (nano::log_config const &, std::optional data_path); + +public: + template + void log (nano::log::level level, nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).log (to_spdlog_level (level), fmt, std::forward (args)...); + } + + template + void debug (nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).debug (fmt, std::forward (args)...); + } + + template + void info (nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).info (fmt, std::forward (args)...); + } + + template + void warn (nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).warn (fmt, std::forward (args)...); + } + + template + void error (nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).error (fmt, std::forward (args)...); + } + + template + void critical (nano::log::type type, spdlog::format_string_t fmt, Args &&... args) + { + get_logger (type).critical (fmt, std::forward (args)...); + } + +public: + template + void trace (nano::log::type type, nano::log::detail detail, Args &&... args) + { + if constexpr (is_tracing_enabled ()) + { + debug_assert (detail != nano::log::detail::all); + + // Include info about precise time of the event + auto now = std::chrono::high_resolution_clock::now (); + + // TODO: Improve code indentation config + auto & logger = get_logger (type, detail); + logger.trace ("{}", + nano::streamed_args (global_tracing_config, + nano::log::arg{ "event", event_formatter{ type, detail } }, + nano::log::arg{ "time", nano::log::microseconds (now) }, + std::forward (args)...)); + } + } + +private: + struct event_formatter final + { + nano::log::type type; + nano::log::detail detail; + + friend std::ostream & operator<< (std::ostream & os, event_formatter const & self) + { + return os << to_string (self.type) << "::" << to_string (self.detail); + } + }; + +private: + const std::string identifier; + + std::map> spd_loggers; + std::shared_mutex mutex; + +private: + spdlog::logger & get_logger (nano::log::type, nano::log::detail = nano::log::detail::all); + std::shared_ptr make_logger (nano::log::logger_id); + nano::log::level find_level (nano::log::logger_id) const; + + static spdlog::level::level_enum to_spdlog_level (nano::log::level); +}; + +/** + * Returns a logger instance that can be used before node specific logging is available. + * Should only be used for logging that happens during startup and initialization, since it won't contain node specific identifier. + */ +nano::logger & default_logger (); +} \ No newline at end of file diff --git a/nano/lib/logging_enums.cpp b/nano/lib/logging_enums.cpp new file mode 100644 index 0000000000..7111ca6591 --- /dev/null +++ b/nano/lib/logging_enums.cpp @@ -0,0 +1,113 @@ +#include +#include + +#include + +std::string_view nano::log::to_string (nano::log::type tag) +{ + return magic_enum::enum_name (tag); +} + +std::string_view nano::log::to_string (nano::log::detail detail) +{ + return magic_enum::enum_name (detail); +} + +std::string_view nano::log::to_string (nano::log::level level) +{ + return magic_enum::enum_name (level); +} + +const std::vector & nano::log::all_levels () +{ + static std::vector all = [] () { + return nano::util::enum_values (); + }(); + return all; +} + +const std::vector & nano::log::all_types () +{ + static std::vector all = [] () { + return nano::util::enum_values (); + }(); + return all; +} + +nano::log::level nano::log::parse_level (std::string_view name) +{ + auto value = nano::util::parse_enum (name); + if (value.has_value ()) + { + return value.value (); + } + else + { + auto all_levels_str = nano::util::join (nano::log::all_levels (), ", ", [] (auto const & lvl) { + return to_string (lvl); + }); + + throw std::invalid_argument ("Invalid log level: " + std::string (name) + ". Must be one of: " + all_levels_str); + } +} + +nano::log::type nano::log::parse_type (std::string_view name) +{ + auto value = nano::util::parse_enum (name); + if (value.has_value ()) + { + return value.value (); + } + else + { + throw std::invalid_argument ("Invalid log type: " + std::string (name)); + } +} + +nano::log::detail nano::log::parse_detail (std::string_view name) +{ + auto value = nano::util::parse_enum (name); + if (value.has_value ()) + { + return value.value (); + } + else + { + throw std::invalid_argument ("Invalid log detail: " + std::string (name)); + } +} + +std::string_view nano::log::to_string (nano::log::tracing_format format) +{ + return magic_enum::enum_name (format); +} + +nano::log::tracing_format nano::log::parse_tracing_format (std::string_view name) +{ + auto value = magic_enum::enum_cast (name); + if (value.has_value ()) + { + return value.value (); + } + else + { + auto all_formats_str = nano::util::join (nano::log::all_tracing_formats (), ", ", [] (auto const & fmt) { + return to_string (fmt); + }); + + throw std::invalid_argument ("Invalid tracing format: " + std::string (name) + ". Must be one of: " + all_formats_str); + } +} + +const std::vector & nano::log::all_tracing_formats () +{ + static std::vector all = [] () { + std::vector result; + for (auto const & fmt : magic_enum::enum_values ()) + { + result.push_back (fmt); + } + return result; + }(); + return all; +} \ No newline at end of file diff --git a/nano/lib/logging_enums.hpp b/nano/lib/logging_enums.hpp new file mode 100644 index 0000000000..eddf9b120a --- /dev/null +++ b/nano/lib/logging_enums.hpp @@ -0,0 +1,212 @@ +#pragma once + +#include +#include +#include + +#include + +namespace nano::log +{ +enum class level +{ + trace, + debug, + info, + warn, + error, + critical, + off, +}; + +enum class type +{ + all = 0, // reserved + + generic, + test, + system, + init, + config, + logging, + node, + node_wrapper, + daemon, + daemon_rpc, + daemon_wallet, + wallet, + qt, + rpc, + rpc_connection, + rpc_callbacks, + rpc_request, + ipc, + ipc_server, + websocket, + tls, + active_transactions, + election, + blockprocessor, + network, + network_processed, + channel, + channel_sent, + socket, + socket_server, + tcp, + tcp_server, + tcp_listener, + prunning, + conf_processor_bounded, + conf_processor_unbounded, + distributed_work, + epoch_upgrader, + opencl_work, + upnp, + rep_crawler, + lmdb, + rocksdb, + txn_tracker, + gap_cache, + vote_processor, + election_scheduler, + vote_generator, + rep_tiers, + + // bootstrap + bulk_pull_client, + bulk_pull_server, + bulk_pull_account_client, + bulk_pull_account_server, + bulk_push_client, + bulk_push_server, + frontier_req_client, + frontier_req_server, + bootstrap, + bootstrap_lazy, + bootstrap_legacy, + + _last // Must be the last enum +}; + +enum class detail +{ + all = 0, // reserved + + test, + + // node + process_confirmed, + + // active_transactions + active_started, + active_stopped, + + // election + election_confirmed, + election_expired, + broadcast_vote, + + // blockprocessor + block_processed, + + // vote_processor + vote_processed, + + // network + message_processed, + message_sent, + message_dropped, + + // election_scheduler + block_activated, + + // vote_generator + candidate_processed, + should_vote, + + // bulk pull/push + pulled_block, + sending_block, + sending_pending, + sending_frontier, + requesting_account_or_head, + requesting_pending, + + // message types + not_a_type, + invalid, + keepalive, + publish, + republish_vote, + confirm_req, + confirm_ack, + node_id_handshake, + telemetry_req, + telemetry_ack, + asc_pull_req, + asc_pull_ack, + bulk_pull, + bulk_push, + frontier_req, + bulk_pull_account, + + _last // Must be the last enum +}; + +// TODO: Additionally categorize logs by categories which can be enabled/disabled independently +enum class category +{ + all = 0, // reserved + + work_generation, + // ... + + _last // Must be the last enum +}; + +enum class tracing_format +{ + standard, + json, +}; +} + +namespace nano::log +{ +std::string_view to_string (nano::log::type); +std::string_view to_string (nano::log::detail); +std::string_view to_string (nano::log::level); + +/// @throw std::invalid_argument if the input string does not match a log::level +nano::log::level parse_level (std::string_view); + +/// @throw std::invalid_argument if the input string does not match a log::type +nano::log::type parse_type (std::string_view); + +/// @throw std::invalid_argument if the input string does not match a log::detail +nano::log::detail parse_detail (std::string_view); + +std::vector const & all_levels (); +std::vector const & all_types (); + +std::string_view to_string (nano::log::tracing_format); +nano::log::tracing_format parse_tracing_format (std::string_view); +std::vector const & all_tracing_formats (); +} + +// Ensure that the enum_range is large enough to hold all values (including future ones) +template <> +struct magic_enum::customize::enum_range +{ + static constexpr int min = 0; + static constexpr int max = 128; +}; + +// Ensure that the enum_range is large enough to hold all values (including future ones) +template <> +struct magic_enum::customize::enum_range +{ + static constexpr int min = 0; + static constexpr int max = 512; +}; \ No newline at end of file diff --git a/nano/lib/memory.hpp b/nano/lib/memory.hpp index 6a484540d3..333a5ff980 100644 --- a/nano/lib/memory.hpp +++ b/nano/lib/memory.hpp @@ -16,8 +16,8 @@ bool get_use_memory_pools (); void set_use_memory_pools (bool use_memory_pools); /** This makes some heuristic assumptions about the implementation defined shared_ptr internals. - Should only be used in the memory pool purge functions at exit, which doesn't matter much if - it is incorrect (other than reports from heap memory analysers) */ + Should only be used in the memory pool purge functions at exit, which doesn't matter much if + it is incorrect (other than reports from heap memory analysers) */ template constexpr size_t determine_shared_ptr_pool_size () { diff --git a/nano/lib/numbers.cpp b/nano/lib/numbers.cpp index 65cb8ac86d..f33d6f3cb3 100644 --- a/nano/lib/numbers.cpp +++ b/nano/lib/numbers.cpp @@ -894,6 +894,27 @@ std::string nano::to_string (double const value_a, int const precision_a) return stream.str (); } +std::ostream & nano::operator<< (std::ostream & os, const uint128_union & val) +{ + // TODO: Replace with streaming implementation + os << val.to_string (); + return os; +} + +std::ostream & nano::operator<< (std::ostream & os, const uint256_union & val) +{ + // TODO: Replace with streaming implementation + os << val.to_string (); + return os; +} + +std::ostream & nano::operator<< (std::ostream & os, const uint512_union & val) +{ + // TODO: Replace with streaming implementation + os << val.to_string (); + return os; +} + #ifdef _WIN32 #pragma warning(push) #pragma warning(disable : 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned diff --git a/nano/lib/numbers.hpp b/nano/lib/numbers.hpp index d73310d1b4..3021524c4c 100644 --- a/nano/lib/numbers.hpp +++ b/nano/lib/numbers.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace nano { @@ -61,6 +62,7 @@ class amount : public uint128_union using uint128_union::uint128_union; }; class raw_key; + class uint256_union { public: @@ -265,6 +267,11 @@ std::string to_string_hex (uint64_t const); std::string to_string_hex (uint16_t const); bool from_string_hex (std::string const &, uint64_t &); +/* Printing adapters */ +std::ostream & operator<< (std::ostream & os, const uint128_union & val); +std::ostream & operator<< (std::ostream & os, const uint256_union & val); +std::ostream & operator<< (std::ostream & os, const uint512_union & val); + /** * Convert a double to string in fixed format * @param precision_a (optional) use a specific precision (default is the maximum) diff --git a/nano/lib/object_stream.cpp b/nano/lib/object_stream.cpp new file mode 100644 index 0000000000..b733fc0eca --- /dev/null +++ b/nano/lib/object_stream.cpp @@ -0,0 +1,28 @@ +#include + +nano::object_stream_config const & nano::object_stream_config::default_config () +{ + static object_stream_config const config{}; + return config; +} + +nano::object_stream_config const & nano::object_stream_config::json_config () +{ + static object_stream_config const config{ + .field_name_begin = "\"", + .field_name_end = "\"", + .field_assignment = ":", + .field_separator = ",", + .object_begin = "{", + .object_end = "}", + .array_begin = "[", + .array_end = "]", + .array_element_begin = "", + .array_element_end = "", + .array_element_separator = ",", + .indent = "", + .newline = "", + .precision = 4, + }; + return config; +} \ No newline at end of file diff --git a/nano/lib/object_stream.hpp b/nano/lib/object_stream.hpp new file mode 100644 index 0000000000..f51e6feb06 --- /dev/null +++ b/nano/lib/object_stream.hpp @@ -0,0 +1,554 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace nano +{ +struct object_stream_config +{ + std::string field_name_begin{ "" }; + std::string field_name_end{ "" }; + std::string field_assignment{ ": " }; + std::string field_separator{ "," }; + + std::string object_begin{ "{" }; + std::string object_end{ "}" }; + + std::string array_begin{ "[" }; + std::string array_end{ "]" }; + + std::string array_element_begin{ "" }; + std::string array_element_end{ "" }; + std::string array_element_separator{ "," }; + + std::string string_begin{ "\"" }; + std::string string_end{ "\"" }; + + std::string true_value{ "true" }; + std::string false_value{ "false" }; + std::string null_value{ "null" }; + + std::string indent{ " " }; + std::string newline{ "\n" }; + + /** Number of decimal places to show for `float` and `double` */ + int precision{ 2 }; + + static object_stream_config const & default_config (); + static object_stream_config const & json_config (); +}; + +class object_stream_context +{ +public: + object_stream_config const & config; + + explicit object_stream_context (std::ostream & os, object_stream_config const & config = object_stream_config::default_config ()) : + os{ os }, + config{ config } + { + } + + // Bump indent level when nesting objects + object_stream_context (object_stream_context const & other) : + os{ other.os }, + config{ other.config }, + indent_level{ other.indent_level + 1 } + { + } + +private: + std::ostream & os; + int indent_level{ 0 }; + bool needs_newline{ false }; + +public: // Keep these defined in the header for inlining + std::ostream & begin_stream () + { + return os; + } + + void begin_field (std::string_view name, bool first) + { + if (!first) + { + os << config.field_separator; + } + if (std::exchange (needs_newline, false)) + { + os << config.newline; + } + indent (); + os << config.field_name_begin << name << config.field_name_end << config.field_assignment; + } + + void end_field () + { + needs_newline = true; + } + + void begin_object () + { + os << config.object_begin; + os << config.newline; + } + + void end_object () + { + os << config.newline; + indent (); + os << config.object_end; + needs_newline = true; + } + + void begin_array () + { + os << config.array_begin; + os << config.newline; + } + + void end_array () + { + os << config.newline; + indent (); + os << config.array_end; + needs_newline = true; + } + + void begin_array_element (bool first) + { + if (!first) + { + os << config.array_element_separator; + } + if (std::exchange (needs_newline, false)) + { + os << config.newline; + } + indent (); + os << config.array_element_begin; + } + + void end_array_element () + { + os << config.array_element_end; + needs_newline = true; + } + + void begin_string () + { + os << config.string_begin; + } + + void end_string () + { + os << config.string_end; + } + +private: + void indent () + { + if (!config.indent.empty ()) + { + for (int i = 0; i < indent_level; ++i) + { + os << config.indent; + } + } + } +}; + +class object_stream; +class array_stream; + +/* + * Concepts used for choosing the correct writing function + */ + +template +concept object_streamable = requires (T const & obj, object_stream & obs) { + { + stream_as (obj, obs) + }; +}; + +template +concept array_streamable = requires (T const & obj, array_stream & ars) { + { + stream_as (obj, ars) + }; +}; + +template +concept object_or_array_streamable = object_streamable || array_streamable; + +class object_stream_base +{ +public: + explicit object_stream_base (object_stream_context const & ctx) : + ctx{ ctx } + { + } + + explicit object_stream_base (std::ostream & os, object_stream_config const & config = object_stream_config::default_config ()) : + ctx{ os, config } + { + } + +protected: + object_stream_context ctx; +}; + +/** + * Used to serialize an object. + * Outputs: `field1: value1, field2: value2, ...` (without enclosing `{}`) + */ +class object_stream : private object_stream_base +{ +public: + // Inherit default constructors + using object_stream_base::object_stream_base; + + object_stream (object_stream const &) = delete; // Disallow copying + +public: + template + void write (std::string_view name, Value const & value) + { + ctx.begin_field (name, std::exchange (first_field, false)); + stream_as_value (value, ctx); + ctx.end_field (); + } + + // Handle `.write_range ("name", container)` + template + inline void write_range (std::string_view name, Container const & container); + + // Handle `.write_range ("name", container, [] (auto const & entry) { ... })` + template + requires (std::is_invocable_v) + void write_range (std::string_view name, Container const & container, Transform transform) + { + write_range (name, std::views::transform (container, transform)); + } + + // Handle `.write_range ("name", container, [] (auto const & entry, nano::object_stream &) { ... })` + template + requires (std::is_invocable_v) + void write_range (std::string_view name, Container const & container, Writer writer) + { + write_range (name, container, [&writer] (auto const & el) { + return [&writer, &el] (object_stream & obs) { + writer (el, obs); + }; + }); + } + + // Handle `.write_range ("name", container, [] (auto const & entry, nano::array_stream &) { ... })` + template + requires (std::is_invocable_v) + void write_range (std::string_view name, Container const & container, Writer writer) + { + write_range (name, container, [&writer] (auto const & el) { + return [&writer, &el] (array_stream & obs) { + writer (el, obs); + }; + }); + } + +private: + bool first_field{ true }; +}; + +/** + * Used to serialize an array of objects. + * Outputs: `[value1, value2, ...]` + */ +class array_stream : private object_stream_base +{ +public: + // Inherit default constructors + using object_stream_base::object_stream_base; + + array_stream (array_stream const &) = delete; // Disallow copying + +public: + template + void write_single (Value const & value) + { + ctx.begin_array_element (std::exchange (first_element, false)); + stream_as_value (value, ctx); + ctx.end_array_element (); + } + + // Handle `.write (container)` + template + void write (Container const & container) + { + for (auto const & el : container) + { + write_single (el); + }; + } + + // Handle `.write (container, [] (auto const & entry) { ... })` + template + requires (std::is_invocable_v) + void write (Container const & container, Transform transform) + { + write (std::views::transform (container, transform)); + } + + // Handle `.write (container, [] (auto const & entry, nano::object_stream &) { ... })` + template + requires (std::is_invocable_v) + void write (Container const & container, Writer writer) + { + write (container, [&writer] (auto const & el) { + return [&writer, &el] (object_stream & obs) { + writer (el, obs); + }; + }); + } + + // Handle `.write_range (container, [] (auto const & entry, nano::array_stream &) { ... })` + template + requires (std::is_invocable_v) + void write (Container const & container, Writer writer) + { + write (container, [&writer] (auto const & el) { + return [&writer, &el] (array_stream & obs) { + writer (el, obs); + }; + }); + } + +private: + bool first_element{ true }; +}; + +/** + * Used for human readable object serialization. Should be used to serialize a single object. + * Outputs: `{ field1: value1, field2: value2, ... }` + */ +class root_object_stream : private object_stream_base +{ +public: + // Inherit default constructors + using object_stream_base::object_stream_base; + +public: + template + void write (Value const & value) + { + stream_as_value (value, ctx); + } + + // Handle `.write_range (container)` + template + inline void write_range (Container const & container); + + // Handle `.write_range (container, [] (auto const & entry) { ... })` + template + requires (std::is_invocable_v) + void write_range (Container const & container, Transform transform) + { + write_range (std::views::transform (container, transform)); + } + + // Handle `.write_range (container, [] (auto const & entry, nano::object_stream &) { ... })` + template + requires (std::is_invocable_v) + void write_range (Container const & container, Writer writer) + { + write_range (container, [&writer] (auto const & el) { + return [&writer, &el] (object_stream & obs) { + writer (el, obs); + }; + }); + } + + // Handle `.write_range (container, [] (auto const & entry, nano::array_stream &) { ... })` + template + requires (std::is_invocable_v) + void write_range (Container const & container, Writer writer) + { + write_range (container, [&writer] (auto const & el) { + return [&writer, &el] (array_stream & obs) { + writer (el, obs); + }; + }); + } +}; + +/* + * Implementation for `write_range` functions + */ + +template +inline void nano::object_stream::write_range (std::string_view name, Container const & container) +{ + write (name, [&container] (array_stream & ars) { + ars.write (container); + }); +} + +template +inline void nano::root_object_stream::write_range (Container const & container) +{ + write ([&container] (array_stream & ars) { + ars.write (container); + }); +} + +/* + * Writers + */ + +template +inline void stream_as_value (Value const & value, object_stream_context & ctx) +{ + // Automatically support printing all enums + using magic_enum::iostream_operators::operator<<; + + ctx.begin_string (); + ctx.begin_stream () << value; // Write using type specific ostream operator + ctx.end_string (); +} + +template +inline void stream_as_value (Value const & value, object_stream_context & ctx) +{ + ctx.begin_object (); + + // Write as object + nano::object_stream obs{ ctx }; + stream_as (value, obs); + + ctx.end_object (); +} + +template +inline void stream_as_value (Value const & value, object_stream_context & ctx) +{ + ctx.begin_array (); + + // Write as array + nano::array_stream ars{ ctx }; + stream_as (value, ars); + + ctx.end_array (); +} + +/* + * Adapters for types implementing convenience `obj(object_stream &)` & `obj(array_stream &)` functions + */ + +template +concept simple_object_streamable = requires (T const & obj, object_stream & obs) { + { + obj (obs) + }; +}; + +template +concept simple_array_streamable = requires (T const & obj, array_stream & ars) { + { + obj (ars) + }; +}; + +template +inline void stream_as (Value const & value, object_stream & obs) +{ + value (obs); +} + +template +inline void stream_as (Value const & value, array_stream & ars) +{ + value (ars); +} +} + +/* + * Specializations for primitive types + */ + +namespace nano +{ +template + requires (std::is_integral_v && sizeof (Value) > 1) // Exclude bool, char, etc. +inline void stream_as_value (const Value & value, object_stream_context & ctx) +{ + ctx.begin_stream () << value; +} + +template + requires (std::is_floating_point_v) +inline void stream_as_value (const Value & value, object_stream_context & ctx) +{ + ctx.begin_stream () << std::fixed << std::setprecision (ctx.config.precision) << value; +} + +inline void stream_as_value (bool const & value, object_stream_context & ctx) +{ + ctx.begin_stream () << (value ? ctx.config.true_value : ctx.config.false_value); +} + +inline void stream_as_value (const int8_t & value, object_stream_context & ctx) +{ + ctx.begin_stream () << static_cast (value); // Avoid printing as char +} + +inline void stream_as_value (const uint8_t & value, object_stream_context & ctx) +{ + ctx.begin_stream () << static_cast (value); // Avoid printing as char +} + +template +inline void stream_as_optional (const Opt & opt, object_stream_context & ctx) +{ + if (opt) + { + stream_as_value (*opt, ctx); + } + else + { + ctx.begin_stream () << ctx.config.null_value; + } +} + +template +inline void stream_as_value (std::shared_ptr const & value, object_stream_context & ctx) +{ + stream_as_optional (value, ctx); +} + +template +inline void stream_as_value (std::unique_ptr const & value, object_stream_context & ctx) +{ + stream_as_optional (value, ctx); +} + +template +inline void stream_as_value (std::weak_ptr const & value, object_stream_context & ctx) +{ + stream_as_optional (value.lock (), ctx); +} + +template +inline void stream_as_value (std::optional const & value, object_stream_context & ctx) +{ + stream_as_optional (value, ctx); +} +} \ No newline at end of file diff --git a/nano/lib/object_stream_adapters.hpp b/nano/lib/object_stream_adapters.hpp new file mode 100644 index 0000000000..29e372c86d --- /dev/null +++ b/nano/lib/object_stream_adapters.hpp @@ -0,0 +1,150 @@ +#pragma once + +#include +#include + +#include +#include + +#include + +namespace nano +{ +template +struct object_stream_formatter +{ + nano::object_stream_config const & config; + Streamable const & value; + Writer writer; + + explicit object_stream_formatter (Streamable const & value, Writer writer, nano::object_stream_config const & config) : + config{ config }, + value{ value }, + writer{ writer } + { + } + + friend std::ostream & operator<< (std::ostream & os, object_stream_formatter const & self) + { + nano::root_object_stream obs{ os, self.config }; + self.writer (self.value, obs); + return os; + } + + // Needed for fmt formatting, uses the ostream operator under the hood + friend auto format_as (object_stream_formatter const & self) + { + return fmt::streamed (self); + } +}; + +enum class streamed_format +{ + basic, + json +}; + +inline nano::object_stream_config const & to_object_stream_config (streamed_format format) +{ + switch (format) + { + case streamed_format::basic: + return nano::object_stream_config::default_config (); + case streamed_format::json: + return nano::object_stream_config::json_config (); + default: + debug_assert (false); + return nano::object_stream_config::default_config (); + } +} + +template +auto streamed (Streamable const & value, streamed_format format = streamed_format::basic) +{ + return object_stream_formatter{ value, [] (auto const & value, nano::root_object_stream & obs) { obs.write (value); }, to_object_stream_config (format) }; +} + +template +auto streamed_range (StreamableRange const & value, streamed_format format = streamed_format::basic) +{ + return object_stream_formatter{ value, [] (auto const & value, nano::root_object_stream & obs) { obs.write_range (value); }, to_object_stream_config (format) }; +} + +/** + * Wraps {name,value} args and provides `<<(std::ostream &, ...)` and fmt format operator that writes the arguments to the stream in a lazy manner. + */ +template +struct object_stream_args_formatter +{ + nano::object_stream_config const & config; + std::tuple args; + + explicit object_stream_args_formatter (nano::object_stream_config const & config, Args &&... args) : + config{ config }, + args{ std::forward (args)... } + { + } + + friend std::ostream & operator<< (std::ostream & os, object_stream_args_formatter const & self) + { + nano::object_stream obs{ os, self.config }; + std::apply ([&obs] (auto &&... args) { + ((obs.write (args.name, args.value)), ...); + }, + self.args); + return os; + } + + // Needed for fmt formatting, uses the ostream operator under the hood + friend auto format_as (object_stream_args_formatter const & val) + { + return fmt::streamed (val); + } +}; + +template +auto streamed_args (nano::object_stream_config const & config, Args &&... args) +{ + return object_stream_args_formatter{ config, std::forward (args)... }; +} +} + +/* + * Adapter that allows for printing using '<<' operator for all classes that implement object streaming + */ +namespace nano::object_stream_adapters +{ +template +std::ostream & operator<< (std::ostream & os, Value const & value) +{ + return os << nano::streamed (value); +} + +template +std::string to_string (Value const & value) +{ + std::stringstream ss; + ss << nano::streamed (value); + return ss.str (); +} + +template +std::string to_json (Value const & value) +{ + std::stringstream ss; + ss << nano::streamed (value, nano::streamed_format::json); + return ss.str (); +} +} + +/* + * Adapter that allows for printing using fmt library for all classes that implement object streaming + */ +template +struct fmt::formatter : fmt::ostream_formatter +{ + auto format (Streamable const & value, format_context & ctx) + { + return fmt::ostream_formatter::format (nano::streamed (value), ctx); + } +}; \ No newline at end of file diff --git a/nano/lib/optional_ptr.hpp b/nano/lib/optional_ptr.hpp index 56695fc3ed..8c5fdc2fe7 100644 --- a/nano/lib/optional_ptr.hpp +++ b/nano/lib/optional_ptr.hpp @@ -55,14 +55,14 @@ class optional_ptr return *ptr; } - T * const operator-> () + T * const operator->() { - return ptr.operator-> (); + return ptr.operator->(); } - T const * const operator-> () const + T const * const operator->() const { - return ptr.operator-> (); + return ptr.operator->(); } T const * const get () const diff --git a/nano/lib/stats_enums.cpp b/nano/lib/stats_enums.cpp index 0e77882d6d..8da30854e9 100644 --- a/nano/lib/stats_enums.cpp +++ b/nano/lib/stats_enums.cpp @@ -1,8 +1,5 @@ #include -#define MAGIC_ENUM_RANGE_MIN 0 -#define MAGIC_ENUM_RANGE_MAX 256 - #include std::string_view nano::to_string (nano::stat::type type) diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index 7473d85c66..6d1ac20b29 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -3,6 +3,8 @@ #include #include +#include + namespace nano::stat { /** Primary statistics type */ @@ -21,6 +23,8 @@ enum class type : uint8_t http_callback, ipc, tcp, + channel, + socket, confirmation_height, confirmation_observer, drop, @@ -32,6 +36,8 @@ enum class type : uint8_t vote_cache, hinting, blockprocessor, + blockprocessor_source, + blockprocessor_result, bootstrap_server, active, active_started, @@ -43,6 +49,9 @@ enum class type : uint8_t election_scheduler, optimistic_scheduler, handshake, + rep_crawler, + local_block_broadcaster, + rep_tiers, bootstrap_ascending, bootstrap_ascending_accounts, @@ -60,11 +69,17 @@ enum class detail : uint8_t loop, total, process, + processed, + ignored, update, + updated, request, broadcast, cleanup, top, + none, + success, + unknown, // processing queue queue, @@ -93,6 +108,7 @@ enum class detail : uint8_t old, gap_previous, gap_source, + rollback, rollback_failed, progress, bad_signature, @@ -104,6 +120,19 @@ enum class detail : uint8_t representative_mismatch, block_position, + // blockprocessor + process_blocking, + process_blocking_timeout, + force, + + // block source + live, + bootstrap, + bootstrap_legacy, + unchecked, + local, + forced, + // message specific not_a_type, invalid, @@ -146,9 +175,19 @@ enum class detail : uint8_t vote_processed, vote_cached, election_block_conflict, + election_restart, + election_not_confirmed, + election_hinted_overflow, + election_hinted_confirmed, + election_hinted_drop, + broadcast_vote, + broadcast_vote_normal, + broadcast_vote_final, generate_vote, generate_vote_normal, generate_vote_final, + broadcast_block_initial, + broadcast_block_repeat, // election types normal, @@ -170,7 +209,7 @@ enum class detail : uint8_t invalid_frontier_req_message, invalid_asc_pull_req_message, invalid_asc_pull_ack_message, - message_too_big, + message_size_too_big, outdated_version, // tcp @@ -208,7 +247,7 @@ enum class detail : uint8_t requests_unknown, // duplicate - duplicate_publish, + duplicate_publish_message, // telemetry invalid_signature, @@ -296,6 +335,24 @@ enum class detail : uint8_t deprioritize, deprioritize_failed, + // rep_crawler + channel_dead, + query_target_failed, + query_channel_busy, + query_sent, + query_duplicate, + rep_timeout, + query_timeout, + query_completion, + crawl_aggressive, + crawl_normal, + + // block broadcaster + broadcast_normal, + broadcast_aggressive, + erase_old, + erase_confirmed, + _last // Must be the last enum }; @@ -311,7 +368,23 @@ enum class dir : uint8_t namespace nano { -std::string_view to_string (stat::type type); -std::string_view to_string (stat::detail detail); -std::string_view to_string (stat::dir dir); +std::string_view to_string (stat::type); +std::string_view to_string (stat::detail); +std::string_view to_string (stat::dir); } + +// Ensure that the enum_range is large enough to hold all values (including future ones) +template <> +struct magic_enum::customize::enum_range +{ + static constexpr int min = 0; + static constexpr int max = 128; +}; + +// Ensure that the enum_range is large enough to hold all values (including future ones) +template <> +struct magic_enum::customize::enum_range +{ + static constexpr int min = 0; + static constexpr int max = 512; +}; diff --git a/nano/lib/thread_roles.cpp b/nano/lib/thread_roles.cpp index 0824d23733..944ac0e1bd 100644 --- a/nano/lib/thread_roles.cpp +++ b/nano/lib/thread_roles.cpp @@ -100,6 +100,15 @@ std::string nano::thread_role::get_string (nano::thread_role::name role) case nano::thread_role::name::scheduler_priority: thread_role_name_string = "Sched Priority"; break; + case nano::thread_role::name::rep_crawler: + thread_role_name_string = "Rep Crawler"; + break; + case nano::thread_role::name::local_block_broadcasting: + thread_role_name_string = "Local broadcast"; + break; + case nano::thread_role::name::rep_tiers: + thread_role_name_string = "Rep tiers"; + break; default: debug_assert (false && "nano::thread_role::get_string unhandled thread role"); } diff --git a/nano/lib/thread_roles.hpp b/nano/lib/thread_roles.hpp index 311ae58d1b..724efad5c8 100644 --- a/nano/lib/thread_roles.hpp +++ b/nano/lib/thread_roles.hpp @@ -42,6 +42,9 @@ enum class name scheduler_manual, scheduler_optimistic, scheduler_priority, + rep_crawler, + local_block_broadcasting, + rep_tiers, }; /* diff --git a/nano/lib/threading.hpp b/nano/lib/threading.hpp index 17b74a4cb2..2877d8672a 100644 --- a/nano/lib/threading.hpp +++ b/nano/lib/threading.hpp @@ -4,6 +4,8 @@ #include +#include + namespace nano { namespace thread_attributes diff --git a/nano/lib/tlsconfig.cpp b/nano/lib/tlsconfig.cpp index 064fce24d8..9af33384b4 100644 --- a/nano/lib/tlsconfig.cpp +++ b/nano/lib/tlsconfig.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -138,7 +138,7 @@ namespace } #endif -nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger_mt & logger_a, std::vector const & config_overrides) +nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger & logger, std::vector const & config_overrides) { nano::error error; auto toml_config_path = nano::get_tls_toml_config_path (data_path_a); @@ -176,9 +176,7 @@ nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nan #ifdef NANO_SECURE_RPC load_certs (config_a, logger_a); #else - auto msg ("https or wss is enabled in the TLS configuration, but the node is not built with NANO_SECURE_RPC"); - std::cerr << msg << std::endl; - logger_a.always_log (msg); + logger.critical (nano::log::type::tls, "HTTPS or WSS is enabled in the TLS configuration, but the node is not built with NANO_SECURE_RPC"); std::exit (1); #endif } diff --git a/nano/lib/tlsconfig.hpp b/nano/lib/tlsconfig.hpp index 3afc605327..bae2a9f9b2 100644 --- a/nano/lib/tlsconfig.hpp +++ b/nano/lib/tlsconfig.hpp @@ -13,7 +13,7 @@ namespace nano { -class logger_mt; +class logger; class jsonconfig; class tomlconfig; @@ -54,5 +54,5 @@ class tls_config final #endif }; -nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger_mt & logger_a, std::vector const & config_overrides = std::vector ()); +nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger &, std::vector const & config_overrides = std::vector ()); } diff --git a/nano/lib/tomlconfig.cpp b/nano/lib/tomlconfig.cpp index bf1bd13eff..ee8d9e6f28 100644 --- a/nano/lib/tomlconfig.cpp +++ b/nano/lib/tomlconfig.cpp @@ -166,8 +166,8 @@ std::shared_ptr nano::tomlconfig::create_array (std::string cons } /** - * Erase keys whose values are equal to the one in \p defaults - */ + * Erase keys whose values are equal to the one in \p defaults + */ void nano::tomlconfig::erase_default_values (tomlconfig & defaults_a) { std::shared_ptr clone = std::dynamic_pointer_cast (tree->clone ()); diff --git a/nano/lib/tomlconfig.hpp b/nano/lib/tomlconfig.hpp index e04af3bc05..140e1b0ab9 100644 --- a/nano/lib/tomlconfig.hpp +++ b/nano/lib/tomlconfig.hpp @@ -171,6 +171,19 @@ class tomlconfig : public nano::configbase return *this; } + template + std::vector> get_values () + { + std::vector> result; + for (auto & entry : *tree) + { + T target{}; + get_config (true, entry.first, target, target); + result.push_back ({ entry.first, target }); + } + return result; + } + protected: template ::value>> tomlconfig & get_config (bool optional, std::string const & key, T & target, T default_value = T ()) diff --git a/nano/lib/utility.hpp b/nano/lib/utility.hpp index 7155ca4760..7b2ce35cab 100644 --- a/nano/lib/utility.hpp +++ b/nano/lib/utility.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -10,8 +11,10 @@ #include #include #include +#include #include +#include #include namespace boost @@ -27,7 +30,7 @@ namespace program_options } } -void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error = ""); +[[noreturn]] void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error = ""); #define release_assert_1(check) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true) #define release_assert_2(check, error_msg) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true, error_msg) @@ -210,3 +213,92 @@ bool elapsed (nano::clock::time_point const & last, Duration duration) return elapsed (last, duration, nano::clock::now ()); } } + +namespace nano::util +{ +/** + * Joins elements with specified delimiter while transforming those elements via specified transform function + */ +template +std::string join (InputIt first, InputIt last, std::string_view delimiter, Func transform) +{ + bool start = true; + std::stringstream ss; + while (first != last) + { + if (start) + { + start = false; + } + else + { + ss << delimiter; + } + ss << transform (*first); + ++first; + } + return ss.str (); +} + +template +std::string join (Container const & container, std::string_view delimiter, Func transform) +{ + return join (container.begin (), container.end (), delimiter, transform); +} + +inline std::vector split (std::string const & input, std::string_view delimiter) +{ + std::vector result; + std::size_t startPos = 0; + std::size_t delimiterPos = input.find (delimiter, startPos); + while (delimiterPos != std::string::npos) + { + std::string token = input.substr (startPos, delimiterPos - startPos); + result.push_back (token); + startPos = delimiterPos + delimiter.length (); + delimiterPos = input.find (delimiter, startPos); + } + result.push_back (input.substr (startPos)); + return result; +} + +template +std::string to_str (T const & val) +{ + return boost::lexical_cast (val); +} + +/** + * Same as `magic_enum::enum_values (...)` but ignores reserved values (starting with underscore) + */ +template +std::vector enum_values () +{ + std::vector result; + for (auto const & [val, name] : magic_enum::enum_entries ()) + { + if (!name.starts_with ('_')) + { + result.push_back (val); + } + } + return result; +} + +/** + * Same as `magic_enum::enum_cast (...)` but ignores reserved values (starting with underscore). + * Case insensitive. + */ +template +std::optional parse_enum (std::string_view name) +{ + if (name.starts_with ('_')) + { + return std::nullopt; + } + else + { + return magic_enum::enum_cast (name, magic_enum::case_insensitive); + } +} +} \ No newline at end of file diff --git a/nano/lib/work.cpp b/nano/lib/work.cpp index 07b27e3979..90a74095ae 100644 --- a/nano/lib/work.cpp +++ b/nano/lib/work.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -23,7 +24,7 @@ std::string nano::to_string (nano::work_version const version_a) return result; } -nano::work_pool::work_pool (nano::network_constants & network_constants, unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> opencl_a) : +nano::work_pool::work_pool (nano::network_constants & network_constants, unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, nano::opencl_work_func_t opencl_a) : network_constants{ network_constants }, ticket (0), done (false), diff --git a/nano/lib/work.hpp b/nano/lib/work.hpp index 70df3b8144..60f84987ec 100644 --- a/nano/lib/work.hpp +++ b/nano/lib/work.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,9 @@ namespace nano { std::string to_string (nano::work_version const version_a); +// type of function that does the work generation with an optional return value +using opencl_work_func_t = std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)>; + class block; class block_details; enum class block_type : uint8_t; @@ -36,7 +40,7 @@ class work_item final class work_pool final { public: - work_pool (nano::network_constants & network_constants, unsigned, std::chrono::nanoseconds = std::chrono::nanoseconds (0), std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> = nullptr); + work_pool (nano::network_constants & network_constants, unsigned, std::chrono::nanoseconds = std::chrono::nanoseconds (0), nano::opencl_work_func_t = nullptr); ~work_pool (); void loop (uint64_t); void stop (); @@ -55,7 +59,7 @@ class work_pool final nano::mutex mutex{ mutex_identifier (mutexes::work_pool) }; nano::condition_variable producer_condition; std::chrono::nanoseconds pow_rate_limiter; - std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> opencl; + nano::opencl_work_func_t opencl; nano::observer_set work_observers; }; diff --git a/nano/load_test/CMakeLists.txt b/nano/load_test/CMakeLists.txt index 71a99cc371..0864ac6cfe 100644 --- a/nano/load_test/CMakeLists.txt +++ b/nano/load_test/CMakeLists.txt @@ -3,5 +3,4 @@ add_executable(load_test entry.cpp) target_link_libraries(load_test test_common Boost::process) include_directories(${CMAKE_SOURCE_DIR}/submodules) -include_directories(${CMAKE_SOURCE_DIR}/submodules/cpptoml/include) include_directories(${CMAKE_SOURCE_DIR}/submodules/gtest/googletest/include) diff --git a/nano/load_test/entry.cpp b/nano/load_test/entry.cpp index db0ecc5f47..7a012fdeb0 100644 --- a/nano/load_test/entry.cpp +++ b/nano/load_test/entry.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -490,6 +492,7 @@ account_info account_info_rpc (boost::asio::io_context & ioc, tcp::resolver::res /** This launches a node and fires a lot of send/recieve RPC requests at it (configurable), then other nodes are tested to make sure they observe these blocks as well. */ int main (int argc, char * const * argv) { + nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); boost::program_options::options_description description ("Command line options"); @@ -650,7 +653,7 @@ int main (int argc, char * const * argv) } // Send from genesis account to different accounts and receive the funds - auto send_receive = std::make_shared (ioc, wallet, nano::dev::genesis->account ().to_account (), destination_account->as_string, send_calls_remaining, primary_node_results); + auto send_receive = std::make_shared (ioc, wallet, nano::dev::genesis_key.pub.to_account (), destination_account->as_string, send_calls_remaining, primary_node_results); boost::asio::strand strand{ ioc.get_executor () }; boost::asio::post (strand, [send_receive] () { diff --git a/nano/nano_node/CMakeLists.txt b/nano/nano_node/CMakeLists.txt index 5da26671ee..48d42d3586 100644 --- a/nano/nano_node/CMakeLists.txt +++ b/nano/nano_node/CMakeLists.txt @@ -18,7 +18,9 @@ add_custom_command( COMMAND nano_node --generate_config node > ${PROJECT_BINARY_DIR}/config-node.toml.sample COMMAND nano_node --generate_config rpc > - ${PROJECT_BINARY_DIR}/config-rpc.toml.sample) + ${PROJECT_BINARY_DIR}/config-rpc.toml.sample + COMMAND nano_node --generate_config log > + ${PROJECT_BINARY_DIR}/config-log.toml.sample) if((NANO_GUI OR RAIBLOCKS_GUI) AND NOT APPLE) if(WIN32) diff --git a/nano/nano_node/daemon.cpp b/nano/nano_node/daemon.cpp index 6344fd8e21..2becd930a5 100644 --- a/nano/nano_node/daemon.cpp +++ b/nano/nano_node/daemon.cpp @@ -20,6 +20,8 @@ #include #include +#include + namespace { void nano_abort_signal_handler (int signum) @@ -59,27 +61,31 @@ volatile sig_atomic_t sig_int_or_term = 0; constexpr std::size_t OPEN_FILE_DESCRIPTORS_LIMIT = 16384; } -void nano_daemon::daemon::run (std::filesystem::path const & data_path, nano::node_flags const & flags) +void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flags const & flags) { + nano::logger::initialize (nano::log_config::daemon_default (), data_path, flags.config_overrides); + + logger.info (nano::log::type::daemon, "Daemon started"); + install_abort_signal_handler (); std::filesystem::create_directories (data_path); boost::system::error_code error_chmod; nano::set_secure_perm_directory (data_path, error_chmod); + std::unique_ptr runner; nano::network_params network_params{ nano::network_constants::active_network }; nano::daemon_config config{ data_path, network_params }; auto error = nano::read_node_config_toml (data_path, config, flags.config_overrides); + nano::set_use_memory_pools (config.node.use_memory_pools); + if (!error) { error = nano::flags_config_conflicts (flags, config.node); } if (!error) { - config.node.logging.init (data_path); - nano::logger_mt logger{ config.node.logging.min_time_between_log_output }; - auto tls_config (std::make_shared ()); error = nano::read_tls_config_toml (data_path, *tls_config, logger); if (error) @@ -93,30 +99,29 @@ void nano_daemon::daemon::run (std::filesystem::path const & data_path, nano::no } boost::asio::io_context io_ctx; - auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work)); - nano::work_pool opencl_work (config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { - return opencl->generate_work (version_a, root_a, difficulty_a, ticket_a); + auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work); + nano::opencl_work_func_t opencl_work_func; + if (opencl) + { + opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { + return opencl->generate_work (version_a, root_a, difficulty_a, ticket_a); + }; } - : std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> (nullptr)); + nano::work_pool opencl_work (config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func); try { - // This avoid a blank prompt during any node initialization delays - auto initialization_text = "Starting up Nano node..."; - std::cout << initialization_text << std::endl; - logger.always_log (initialization_text); + // This avoids a blank prompt during any node initialization delays + logger.info (nano::log::type::daemon, "Starting up Nano node..."); // Print info about number of logical cores detected, those are used to decide how many IO, worker and signature checker threads to spawn - logger.always_log (boost::format ("Hardware concurrency: %1% ( configured: %2% )") % std::thread::hardware_concurrency () % nano::hardware_concurrency ()); + logger.info (nano::log::type::daemon, "Hardware concurrency: {} ( configured: {} )", std::thread::hardware_concurrency (), nano::hardware_concurrency ()); nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT); auto const file_descriptor_limit = nano::get_file_descriptor_limit (); + logger.info (nano::log::type::daemon, "File descriptors limit: {}", file_descriptor_limit); if (file_descriptor_limit < OPEN_FILE_DESCRIPTORS_LIMIT) { - logger.always_log (boost::format ("WARNING: open file descriptors limit is %1%, lower than the %2% recommended. Node was unable to change it.") % file_descriptor_limit % OPEN_FILE_DESCRIPTORS_LIMIT); - } - else - { - logger.always_log (boost::format ("Open file descriptors limit is %1%") % file_descriptor_limit); + logger.warn (nano::log::type::daemon, "File descriptors limit is lower than the {} recommended. Node was unable to change it.", OPEN_FILE_DESCRIPTORS_LIMIT); } // for the daemon start up, if the user hasn't specified a port in @@ -133,18 +138,15 @@ void nano_daemon::daemon::run (std::filesystem::path const & data_path, nano::no auto network_label = node->network_params.network.get_current_network_as_string (); std::time_t dateTime = std::time (nullptr); - std::cout << "Network: " << network_label << ", version: " << NANO_VERSION_STRING << "\n" - << "Path: " << node->application_path.string () << "\n" - << "Build Info: " << BUILD_INFO << "\n" - << "Database backend: " << node->store.vendor_get () << "\n" - << "Start time: " << std::put_time (std::gmtime (&dateTime), "%c UTC") << std::endl; + logger.info (nano::log::type::daemon, "Network: {}", network_label); + logger.info (nano::log::type::daemon, "Version: {}", NANO_VERSION_STRING); + logger.info (nano::log::type::daemon, "Data path: '{}'", node->application_path.string ()); + logger.info (nano::log::type::daemon, "Build info: {}", BUILD_INFO); + logger.info (nano::log::type::daemon, "Database backend: {}", node->store.vendor_get ()); + logger.info (nano::log::type::daemon, "Start time: {:%c} UTC", fmt::gmtime (dateTime)); - auto voting (node->wallets.reps ().voting); - if (voting > 1) - { - std::cout << "Voting with more than one representative can limit performance: " << voting << " representatives are configured" << std::endl; - } node->start (); + nano::ipc::ipc_server ipc_server (*node, config.rpc); std::unique_ptr rpc_process; std::unique_ptr rpc; @@ -187,7 +189,9 @@ void nano_daemon::daemon::run (std::filesystem::path const & data_path, nano::no } debug_assert (!nano::signal_handler_impl); - nano::signal_handler_impl = [&io_ctx] () { + nano::signal_handler_impl = [this, &io_ctx] () { + logger.warn (nano::log::type::daemon, "Interrupt signal received, stopping..."); + io_ctx.stop (); sig_int_or_term = 1; }; @@ -219,16 +223,18 @@ void nano_daemon::daemon::run (std::filesystem::path const & data_path, nano::no } else { - std::cerr << "Error initializing node\n"; + logger.critical (nano::log::type::daemon, "Error initializing node"); } } catch (std::runtime_error const & e) { - std::cerr << "Error while running node (" << e.what () << ")\n"; + logger.critical (nano::log::type::daemon, "Error while running node: {}", e.what ()); } } else { - std::cerr << "Error deserializing config: " << error.get_message () << std::endl; + logger.critical (nano::log::type::daemon, "Error deserializing config: {}", error.get_message ()); } + + logger.info (nano::log::type::daemon, "Daemon exiting"); } diff --git a/nano/nano_node/daemon.hpp b/nano/nano_node/daemon.hpp index d56a26c907..8fcc69787c 100644 --- a/nano/nano_node/daemon.hpp +++ b/nano/nano_node/daemon.hpp @@ -1,11 +1,13 @@ +#include + namespace nano { class node_flags; -} -namespace nano_daemon -{ + class daemon { + nano::logger logger{ "daemon" }; + public: void run (std::filesystem::path const &, nano::node_flags const & flags); }; diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 250428f542..97268e8849 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include @@ -53,8 +55,11 @@ class address_library_pair int main (int argc, char * const * argv) { - nano::set_umask (); + nano::set_umask (); // Make sure the process umask is set before any files are created + nano::logger::initialize (nano::log_config::cli_default ()); + nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; + boost::program_options::options_description description ("Command line options"); // clang-format off description.add_options () @@ -138,7 +143,7 @@ int main (int argc, char * const * argv) { if (vm.count ("daemon") > 0) { - nano_daemon::daemon daemon; + nano::daemon daemon; nano::node_flags flags; auto flags_ec = nano::update_flags (flags, vm); if (flags_ec) @@ -281,14 +286,14 @@ int main (int argc, char * const * argv) { if (sample.diff > log_threshold) { - node->logger.always_log (sample.get_entry ()); + std::cout << '\t' << sample.get_entry () << '\n'; } } for (auto const & newcomer : newcomers) { if (newcomer.second > log_threshold) { - node->logger.always_log (newcomer_entry (newcomer)); + std::cout << '\t' << newcomer_entry (newcomer) << '\n'; } } } @@ -610,13 +615,17 @@ int main (int argc, char * const * argv) error |= device >= environment.platforms[platform].devices.size (); if (!error) { - nano::logger_mt logger; + nano::logger logger; nano::opencl_config config (platform, device, threads); - auto opencl (nano::opencl_work::create (true, config, logger, network_params.work)); - nano::work_pool work_pool{ network_params.network, 0, std::chrono::nanoseconds (0), opencl ? [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic &) { - return opencl->generate_work (version_a, root_a, difficulty_a); - } - : std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> (nullptr) }; + auto opencl = nano::opencl_work::create (true, config, logger, network_params.work); + nano::opencl_work_func_t opencl_work_func; + if (opencl) + { + opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic &) { + return opencl->generate_work (version_a, root_a, difficulty_a); + }; + } + nano::work_pool work_pool{ network_params.network, 0, std::chrono::nanoseconds (0), opencl_work_func }; nano::change_block block (0, 0, nano::keypair ().prv, 0, 0); std::cerr << boost::str (boost::format ("Starting OpenCL generation profiling. Platform: %1%. Device: %2%. Threads: %3%. Difficulty: %4$#x (%5%x from base difficulty %6$#x)\n") % platform % device % threads % difficulty % nano::to_string (nano::difficulty::to_multiplier (difficulty, nano::work_thresholds::publish_full.base), 4) % nano::work_thresholds::publish_full.base); for (uint64_t i (0); true; ++i) @@ -987,7 +996,6 @@ int main (int argc, char * const * argv) } } - node->block_processor.flush (); auto end (std::chrono::high_resolution_clock::now ()); auto time (std::chrono::duration_cast (end - begin).count ()); node->stop (); @@ -1027,7 +1035,7 @@ int main (int argc, char * const * argv) .build (); genesis_latest = send->hash (); - node->ledger.process (transaction, *send); + node->ledger.process (transaction, send); auto open = builder.state () .account (keys[i].pub) @@ -1039,7 +1047,7 @@ int main (int argc, char * const * argv) .work (*node->work.generate (nano::work_version::work_1, keys[i].pub, node->network_params.work.epoch_1)) .build (); - node->ledger.process (transaction, *open); + node->ledger.process (transaction, open); } // Generating blocks std::deque> blocks; @@ -1080,7 +1088,10 @@ int main (int argc, char * const * argv) node->process_active (block); blocks.pop_front (); } - node->block_processor.flush (); + while (node->block_processor.size () > 0) + { + std::this_thread::sleep_for (std::chrono::milliseconds (100)); + } // Processing votes std::cerr << boost::str (boost::format ("Starting processing %1% votes\n") % max_votes); auto begin (std::chrono::high_resolution_clock::now ()); @@ -1121,10 +1132,8 @@ int main (int argc, char * const * argv) boost::asio::io_context io_ctx1; boost::asio::io_context io_ctx2; nano::work_pool work{ network_params.network, std::numeric_limits::max () }; - nano::logging logging; auto path1 (nano::unique_path ()); auto path2 (nano::unique_path ()); - logging.init (path1); std::vector config_overrides; auto config (vm.find ("config")); if (config != vm.end ()) @@ -1190,7 +1199,6 @@ int main (int argc, char * const * argv) { node1->block_processor.add (block); } - node1->block_processor.flush (); auto iteration (0); while (node1->ledger.cache.block_count != count * 2 + 1) { @@ -1240,7 +1248,6 @@ int main (int argc, char * const * argv) node2->block_processor.add (block); blocks.pop_front (); } - node2->block_processor.flush (); while (node2->ledger.cache.block_count != count * 2 + 1) { std::this_thread::sleep_for (std::chrono::milliseconds (500)); @@ -1406,17 +1413,17 @@ int main (int argc, char * const * argv) auto hash (info.open_block); nano::block_hash calculated_hash (0); - auto block (node->store.block.get (transaction, hash)); // Block data + auto block = node->ledger.block (transaction, hash); // Block data uint64_t height (0); if (node->ledger.pruning && confirmation_height_info.height != 0) { hash = confirmation_height_info.frontier; - block = node->store.block.get (transaction, hash); + block = node->ledger.block (transaction, hash); // Iteration until pruned block bool pruned_block (false); while (!pruned_block && !block->previous ().is_zero ()) { - auto previous_block (node->store.block.get (transaction, block->previous ())); + auto previous_block = node->ledger.block (transaction, block->previous ()); if (previous_block != nullptr) { hash = previous_block->hash (); @@ -1489,13 +1496,13 @@ int main (int argc, char * const * argv) bool error_or_pruned (false); if (!state_block.hashables.previous.is_zero ()) { - prev_balance = node->ledger.balance_safe (transaction, state_block.hashables.previous, error_or_pruned); + prev_balance = node->ledger.balance (transaction, state_block.hashables.previous).value_or (0); } if (node->ledger.is_epoch_link (state_block.hashables.link)) { if ((state_block.hashables.balance == prev_balance && !error_or_pruned) || (node->ledger.pruning && error_or_pruned && block->sideband ().details.is_epoch)) { - invalid = validate_message (node->ledger.epoch_signer (block->link ()), hash, block->block_signature ()); + invalid = validate_message (node->ledger.epoch_signer (block->link_field ().value ()), hash, block->block_signature ()); } } } @@ -1513,23 +1520,22 @@ int main (int argc, char * const * argv) } else { - bool error_or_pruned (false); - auto prev_balance (node->ledger.balance_safe (transaction, block->previous (), error_or_pruned)); - if (!node->ledger.pruning || !error_or_pruned) + auto prev_balance = node->ledger.balance (transaction, block->previous ()); + if (!node->ledger.pruning || prev_balance) { - if (block->balance () < prev_balance) + if (block->balance () < prev_balance.value ()) { // State send block_details_error = !sideband.details.is_send || sideband.details.is_receive || sideband.details.is_epoch; } else { - if (block->link ().is_zero ()) + if (block->is_change ()) { // State change block_details_error = sideband.details.is_send || sideband.details.is_receive || sideband.details.is_epoch; } - else if (block->balance () == prev_balance && node->ledger.is_epoch_link (block->link ())) + else if (block->balance () == prev_balance.value () && node->ledger.is_epoch_link (block->link_field ().value ())) { // State epoch block_details_error = !sideband.details.is_epoch || sideband.details.is_send || sideband.details.is_receive; @@ -1538,7 +1544,7 @@ int main (int argc, char * const * argv) { // State receive block_details_error = !sideband.details.is_receive || sideband.details.is_send || sideband.details.is_epoch; - block_details_error |= !node->ledger.block_or_pruned_exists (transaction, block->link ().as_block_hash ()); + block_details_error |= !node->ledger.block_or_pruned_exists (transaction, block->source ()); } } } @@ -1552,7 +1558,7 @@ int main (int argc, char * const * argv) print_error_message (boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ())); } // Check link epoch version - if (sideband.details.is_receive && (!node->ledger.pruning || !node->store.pruned.exists (transaction, block->link ().as_block_hash ()))) + if (sideband.details.is_receive && (!node->ledger.pruning || !node->store.pruned.exists (transaction, block->source ()))) { if (sideband.source_epoch != node->ledger.version (*block)) { @@ -1579,14 +1585,14 @@ int main (int argc, char * const * argv) // Calculate representative block if (block->type () == nano::block_type::open || block->type () == nano::block_type::change || block->type () == nano::block_type::state) { - calculated_representative = block->representative (); + calculated_representative = block->representative_field ().value (); } // Retrieving successor block hash hash = node->store.block.successor (transaction, hash); // Retrieving block data if (!hash.is_zero ()) { - block = node->store.block.get (transaction, hash); + block = node->ledger.block (transaction, hash); } } // Check if required block exists @@ -1671,7 +1677,7 @@ int main (int argc, char * const * argv) std::cout << boost::str (boost::format ("%1% pending blocks validated\n") % count); } // Check block existance - auto block (node->store.block.get (transaction, key.hash)); + auto block = node->ledger.block (transaction, key.hash); bool pruned (false); if (block == nullptr) { @@ -1688,11 +1694,11 @@ int main (int argc, char * const * argv) bool previous_pruned = node->ledger.pruning && node->store.pruned.exists (transaction, block->previous ()); if (previous_pruned) { - block = node->store.block.get (transaction, key.hash); + block = node->ledger.block (transaction, key.hash); } if (auto state = dynamic_cast (block.get ())) { - if (node->ledger.is_send (transaction, *state)) + if (state->is_send ()) { destination = state->hashables.link.as_account (); } @@ -1795,7 +1801,7 @@ int main (int argc, char * const * argv) while (!hash.is_zero ()) { // Retrieving block data - auto block (source_node->store.block.get (transaction, hash)); + auto block = source_node->ledger.block (transaction, hash); if (block != nullptr) { ++count; @@ -1804,7 +1810,7 @@ int main (int argc, char * const * argv) std::cout << boost::str (boost::format ("%1% blocks retrieved") % count) << std::endl; } node.node->block_processor.add (block); - if (block->type () == nano::block_type::state && block->previous ().is_zero () && source_node->ledger.is_epoch_link (block->link ())) + if (block->type () == nano::block_type::state && block->previous ().is_zero () && source_node->ledger.is_epoch_link (block->link_field ().value ())) { // Epoch open blocks can be rejected without processed pending blocks to account, push it later again epoch_open_blocks.push_back (block); @@ -1835,8 +1841,6 @@ int main (int argc, char * const * argv) } } - node.node->block_processor.flush (); - auto end (std::chrono::high_resolution_clock::now ()); auto time (std::chrono::duration_cast (end - begin).count ()); auto us_in_second (1000000); @@ -1871,7 +1875,7 @@ int main (int argc, char * const * argv) nano::update_flags (node_flags, vm); nano::inactive_node inactive_node (data_path, node_flags); auto node = inactive_node.node; - node->ledger_pruning (node_flags.block_processor_batch_size != 0 ? node_flags.block_processor_batch_size : 16 * 1024, true, true); + node->ledger_pruning (node_flags.block_processor_batch_size != 0 ? node_flags.block_processor_batch_size : 16 * 1024, true); } else if (vm.count ("debug_stacktrace")) { @@ -1879,15 +1883,12 @@ int main (int argc, char * const * argv) } else if (vm.count ("debug_sys_logging")) { -#ifdef BOOST_WINDOWS - if (!nano::event_log_reg_entry_exists () && !nano::is_windows_elevated ()) - { - std::cerr << "The event log requires the HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Nano\\Nano registry entry, run again as administator to create it.\n"; - return 1; - } -#endif auto inactive_node = nano::default_inactive_node (data_path, vm); - inactive_node->node->logger.always_log (nano::severity_level::error, "Testing system logger"); + inactive_node->node->logger.critical ({}, "Testing system logger (CRITICAL)"); + inactive_node->node->logger.error ({}, "Testing system logger (ERROR)"); + inactive_node->node->logger.warn ({}, "Testing system logger (WARN)"); + inactive_node->node->logger.info ({}, "Testing system logger (INFO)"); + inactive_node->node->logger.debug ({}, "Testing system logger (DEBUG)"); } else if (vm.count ("debug_account_versions")) { diff --git a/nano/nano_rpc/entry.cpp b/nano/nano_rpc/entry.cpp index 415beb9f5f..65e1de81e9 100644 --- a/nano/nano_rpc/entry.cpp +++ b/nano/nano_rpc/entry.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -11,34 +12,24 @@ #include #include -#include -#include +#include #include namespace { -void logging_init (std::filesystem::path const & application_path_a) -{ - static std::atomic_flag logging_already_added = ATOMIC_FLAG_INIT; - if (!logging_already_added.test_and_set ()) - { - boost::log::add_common_attributes (); - auto path = application_path_a / "log"; - - uintmax_t max_size{ 128 * 1024 * 1024 }; - uintmax_t rotation_size{ 4 * 1024 * 1024 }; - bool flush{ true }; - boost::log::add_file_log (boost::log::keywords::target = path, boost::log::keywords::file_name = path / "rpc_log_%Y-%m-%d_%H-%M-%S.%N.log", boost::log::keywords::rotation_size = rotation_size, boost::log::keywords::auto_flush = flush, boost::log::keywords::scan_method = boost::log::sinks::file::scan_method::scan_matching, boost::log::keywords::max_size = max_size, boost::log::keywords::format = "[%TimeStamp%]: %Message%"); - } -} - volatile sig_atomic_t sig_int_or_term = 0; +nano::logger logger{ "rpc_daemon" }; + void run (std::filesystem::path const & data_path, std::vector const & config_overrides) { + logger.info (nano::log::type::daemon_rpc, "Daemon started (RPC)"); + std::filesystem::create_directories (data_path); + boost::system::error_code error_chmod; nano::set_secure_perm_directory (data_path, error_chmod); + std::unique_ptr runner; nano::network_params network_params{ nano::network_constants::active_network }; @@ -46,14 +37,11 @@ void run (std::filesystem::path const & data_path, std::vector cons auto error = nano::read_rpc_config_toml (data_path, rpc_config, config_overrides); if (!error) { - logging_init (data_path); - nano::logger_mt logger; - auto tls_config (std::make_shared ()); error = nano::read_tls_config_toml (data_path, *tls_config, logger); if (error) { - std::cerr << error.get_message () << std::endl; + logger.critical (nano::log::type::daemon, "Error reading RPC TLS config: {}", error.get_message ()); std::exit (1); } else @@ -88,19 +76,22 @@ void run (std::filesystem::path const & data_path, std::vector cons } catch (std::runtime_error const & e) { - std::cerr << "Error while running rpc (" << e.what () << ")\n"; + logger.critical (nano::log::type::daemon, "Error while running RPC: {}", e.what ()); } } else { - std::cerr << "Error deserializing config: " << error.get_message () << std::endl; + logger.critical (nano::log::type::daemon, "Error deserializing config: {}", error.get_message ()); } + + logger.info (nano::log::type::daemon_rpc, "Daemon stopped (RPC)"); } } int main (int argc, char * const * argv) { - nano::set_umask (); + nano::set_umask (); // Make sure the process umask is set before any files are created + nano::logger::initialize (nano::log_config::cli_default ()); boost::program_options::options_description description ("Command line options"); diff --git a/nano/nano_wallet/entry.cpp b/nano/nano_wallet/entry.cpp index 440e5ddf80..69d8262aa7 100644 --- a/nano/nano_wallet/entry.cpp +++ b/nano/nano_wallet/entry.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -25,13 +26,18 @@ namespace { +nano::logger logger{ "wallet_daemon" }; + void show_error (std::string const & message_a) { + logger.critical (nano::log::type::daemon, "{}", message_a); + QMessageBox message (QMessageBox::Critical, "Error starting Nano", message_a.c_str ()); message.setModal (true); message.show (); message.exec (); } + void show_help (std::string const & message_a) { QMessageBox message (QMessageBox::NoIcon, "Help", "see launch options "); @@ -68,6 +74,10 @@ nano::error read_wallet_config (nano::wallet_config & config_a, std::filesystem: int run_wallet (QApplication & application, int argc, char * const * argv, std::filesystem::path const & data_path, nano::node_flags const & flags) { + nano::logger::initialize (nano::log_config::daemon_default (), data_path, flags.config_overrides); + + logger.info (nano::log::type::daemon_wallet, "Daemon started (wallet)"); + int result (0); nano_qt::eventloop_processor processor; boost::system::error_code error_chmod; @@ -99,9 +109,6 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std:: { nano::set_use_memory_pools (config.node.use_memory_pools); - config.node.logging.init (data_path); - nano::logger_mt logger{ config.node.logging.min_time_between_log_output }; - auto tls_config (std::make_shared ()); error = nano::read_tls_config_toml (data_path, *tls_config, logger); if (error) @@ -121,11 +128,15 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std:: std::shared_ptr node; std::shared_ptr gui; nano::set_application_icon (application); - auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work)); - nano::work_pool work{ config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic &) { - return opencl->generate_work (version_a, root_a, difficulty_a); - } - : std::function (nano::work_version const, nano::root const &, uint64_t, std::atomic &)> (nullptr) }; + auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work); + nano::opencl_work_func_t opencl_work_func; + if (opencl) + { + opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic &) { + return opencl->generate_work (version_a, root_a, difficulty_a); + }; + } + nano::work_pool work{ config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func }; node = std::make_shared (io_ctx, data_path, config.node, work, flags); if (!node->init_error ()) { @@ -231,12 +242,17 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std:: splash->hide (); show_error ("Error deserializing config: " + error.get_message ()); } + + logger.info (nano::log::type::daemon_wallet, "Daemon exiting (wallet)"); + return result; } int main (int argc, char * const * argv) { - nano::set_umask (); + nano::set_umask (); // Make sure the process umask is set before any files are created + nano::logger::initialize (nano::log_config::cli_default ()); + nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; QApplication application (argc, const_cast (argv)); diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index b4de400f8f..f8f3b5407e 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -20,16 +20,6 @@ add_library( backlog_population.cpp bandwidth_limiter.hpp bandwidth_limiter.cpp - block_arrival.hpp - block_arrival.cpp - block_broadcast.cpp - block_broadcast.hpp - block_publisher.cpp - block_publisher.hpp - gap_tracker.cpp - gap_tracker.hpp - blocking_observer.cpp - blocking_observer.hpp blockprocessor.hpp blockprocessor.cpp bootstrap/block_deserializer.hpp @@ -88,8 +78,6 @@ add_library( election_insertion_result.hpp epoch_upgrader.hpp epoch_upgrader.cpp - gap_cache.hpp - gap_cache.cpp inactive_cache_information.hpp inactive_cache_information.cpp inactive_cache_status.hpp @@ -110,8 +98,8 @@ add_library( ipc/ipc_server.cpp json_handler.hpp json_handler.cpp - logging.hpp - logging.cpp + local_block_broadcaster.cpp + local_block_broadcaster.hpp make_store.hpp make_store.cpp network.hpp @@ -138,6 +126,8 @@ add_library( process_live_dispatcher.hpp repcrawler.hpp repcrawler.cpp + rep_tiers.hpp + rep_tiers.cpp request_aggregator.hpp request_aggregator.cpp scheduler/bucket.cpp @@ -204,8 +194,6 @@ target_link_libraries( argon2 lmdb Boost::beast - Boost::log_setup - Boost::log Boost::program_options Boost::stacktrace Boost::system @@ -223,6 +211,5 @@ target_compile_definitions( add_dependencies(node ipc_flatbuffers_lib) include_directories(${CMAKE_SOURCE_DIR}/submodules) -include_directories(${CMAKE_SOURCE_DIR}/submodules/cpptoml/include) include_directories( ${CMAKE_SOURCE_DIR}/submodules/nano-pow-server/deps/cpptoml/include) diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index f3581f5b56..be79107759 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,15 +8,17 @@ #include #include #include +#include #include #include using namespace std::chrono; -nano::active_transactions::active_transactions (nano::node & node_a, nano::confirmation_height_processor & confirmation_height_processor_a) : - confirmation_height_processor{ confirmation_height_processor_a }, +nano::active_transactions::active_transactions (nano::node & node_a, nano::confirmation_height_processor & confirmation_height_processor_a, nano::block_processor & block_processor_a) : node{ node_a }, + confirmation_height_processor{ confirmation_height_processor_a }, + block_processor{ block_processor_a }, recently_confirmed{ 65536 }, recently_cemented{ node.config.confirmation_history_size }, election_time_to_live{ node_a.network_params.network.is_dev_network () ? 0s : 2s } @@ -31,6 +34,18 @@ nano::active_transactions::active_transactions (nano::node & node_a, nano::confi confirmation_height_processor.add_block_already_cemented_observer ([this] (nano::block_hash const & hash_a) { this->block_already_cemented_callback (hash_a); }); + + // Notify elections about alternative (forked) blocks + block_processor.block_processed.add ([this] (auto const & result, auto const & context) { + switch (result) + { + case nano::block_status::fork: + publish (context.block); + break; + default: + break; + } + }); } nano::active_transactions::~active_transactions () @@ -151,8 +166,10 @@ void nano::active_transactions::handle_confirmation (nano::store::read_transacti void nano::active_transactions::handle_block_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr const & block, nano::block_hash const & hash, nano::account & account, nano::uint128_t & amount, bool & is_state_send, bool & is_state_epoch, nano::account & pending_account) { - auto destination = block->link ().is_zero () ? block->destination () : block->link ().as_account (); - node.receive_confirmed (transaction, hash, destination); + if (block->is_send ()) + { + node.receive_confirmed (transaction, hash, block->destination ()); + } node.process_confirmed_data (transaction, block, hash, account, amount, is_state_send, is_state_epoch, pending_account); } @@ -172,7 +189,7 @@ void nano::active_transactions::notify_observers (nano::election_status const & void nano::active_transactions::handle_final_votes_confirmation (std::shared_ptr const & block, nano::store::read_transaction const & transaction, nano::election_status_type status) { - auto const & account = !block->account ().is_zero () ? block->account () : block->sideband ().account; + auto account = block->account (); bool is_canary_not_set = !node.ledger.cache.final_votes_confirmation_canary.load (); bool is_canary_account = account == node.network_params.ledger.final_votes_canary_account; @@ -196,12 +213,11 @@ void nano::active_transactions::handle_final_votes_confirmation (std::shared_ptr void nano::active_transactions::activate_successors (const nano::account & account, std::shared_ptr const & block, nano::store::read_transaction const & transaction) { node.scheduler.priority.activate (account, transaction); - auto const & destination = node.ledger.block_destination (transaction, *block); // Start or vote for the next unconfirmed block in the destination account - if (!destination.is_zero () && destination != account) + if (block->is_send () && !block->destination ().is_zero () && block->destination () != account) { - node.scheduler.priority.activate (destination, transaction); + node.scheduler.priority.activate (block->destination (), transaction); } } @@ -300,11 +316,6 @@ void nano::active_transactions::request_confirm (nano::unique_lock solicitor.flush (); lock_a.lock (); - - if (node.config.logging.timing_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Processed %1% elections (%2% were already confirmed) in %3% %4%") % this_loop_target_l % (this_loop_target_l - unconfirmed_count_l) % elapsed.value ().count () % elapsed.unit ())); - } } void nano::active_transactions::cleanup_election (nano::unique_lock & lock_a, std::shared_ptr election) @@ -313,7 +324,6 @@ void nano::active_transactions::cleanup_election (nano::unique_lock debug_assert (lock_a.owns_lock ()); debug_assert (!election->confirmed () || recently_confirmed.exists (election->qualified_root)); - node.stats.inc (completion_type (*election), nano::to_stat_detail (election->behavior ())); // Keep track of election count by election type debug_assert (count_by_behavior[election->behavior ()] > 0); count_by_behavior[election->behavior ()]--; @@ -325,10 +335,16 @@ void nano::active_transactions::cleanup_election (nano::unique_lock (void)erased; debug_assert (erased == 1); } + roots.get ().erase (roots.get ().find (election->qualified_root)); + node.stats.inc (completion_type (*election), to_stat_detail (election->behavior ())); + node.logger.trace (nano::log::type::active_transactions, nano::log::detail::active_stopped, nano::log::arg{ "election", election }); + lock_a.unlock (); + vacancy_update (); + for (auto const & [hash, block] : blocks_l) { // Notify observers about dropped elections & blocks lost confirmed elections @@ -343,11 +359,6 @@ void nano::active_transactions::cleanup_election (nano::unique_lock node.network.publish_filter.clear (block); } } - - if (node.config.logging.election_result_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Election erased for root %1%, confirmed: %2$b") % election->qualified_root.to_string () % election->confirmed ())); - } } nano::stat::type nano::active_transactions::completion_type (nano::election const & election) const @@ -427,7 +438,9 @@ nano::election_insertion_result nano::active_transactions::insert (std::shared_p nano::election_insertion_result result; if (stopped) + { return result; + } auto const root = block_a->qualified_root (); auto const hash = block_a->hash (); @@ -448,6 +461,11 @@ nano::election_insertion_result nano::active_transactions::insert (std::shared_p // Keep track of election count by election type debug_assert (count_by_behavior[result.election->behavior ()] >= 0); count_by_behavior[result.election->behavior ()]++; + + node.stats.inc (nano::stat::type::active_started, to_stat_detail (election_behavior_a)); + node.logger.trace (nano::log::type::active_transactions, nano::log::detail::active_started, + nano::log::arg{ "behavior", election_behavior_a }, + nano::log::arg{ "election", result.election }); } else { @@ -463,11 +481,13 @@ nano::election_insertion_result nano::active_transactions::insert (std::shared_p if (result.inserted) { + release_assert (result.election); + if (auto const cache = node.vote_cache.find (hash); cache) { cache->fill (result.election); } - node.stats.inc (nano::stat::type::active_started, nano::to_stat_detail (election_behavior_a)); + node.observers.active_started.notify (hash); vacancy_update (); } diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index ac83c4efa8..c2b945a9a9 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -25,6 +25,7 @@ class node; class active_transactions; class block; class block_sideband; +class block_processor; class election; class vote; class confirmation_height_processor; @@ -130,7 +131,7 @@ class active_transactions final std::unordered_map> blocks; public: - active_transactions (nano::node &, nano::confirmation_height_processor &); + active_transactions (nano::node &, nano::confirmation_height_processor &, nano::block_processor &); ~active_transactions (); void start (); @@ -204,8 +205,9 @@ class active_transactions final void notify_observers (nano::election_status const & status, std::vector const & votes, nano::account const & account, nano::uint128_t amount, bool is_state_send, bool is_state_epoch, nano::account const & pending_account); private: // Dependencies - nano::confirmation_height_processor & confirmation_height_processor; nano::node & node; + nano::confirmation_height_processor & confirmation_height_processor; + nano::block_processor & block_processor; public: recently_confirmed_cache recently_confirmed; diff --git a/nano/node/backlog_population.hpp b/nano/node/backlog_population.hpp index 41116e5f29..7bc1a6d00e 100644 --- a/nano/node/backlog_population.hpp +++ b/nano/node/backlog_population.hpp @@ -15,8 +15,9 @@ class transaction; } namespace nano { -class stats; +class account_info; class election_scheduler; +class stats; class backlog_population final { diff --git a/nano/node/block_arrival.cpp b/nano/node/block_arrival.cpp deleted file mode 100644 index 914e18dcc0..0000000000 --- a/nano/node/block_arrival.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -bool nano::block_arrival::add (nano::block_hash const & hash_a) -{ - nano::lock_guard lock{ mutex }; - auto now (std::chrono::steady_clock::now ()); - auto inserted (arrival.get ().emplace_back (nano::block_arrival_info{ now, hash_a })); - auto result (!inserted.second); - return result; -} - -bool nano::block_arrival::recent (nano::block_hash const & hash_a) -{ - nano::lock_guard lock{ mutex }; - auto now (std::chrono::steady_clock::now ()); - while (arrival.size () > arrival_size_min && arrival.get ().front ().arrival + arrival_time_min < now) - { - arrival.get ().pop_front (); - } - return arrival.get ().find (hash_a) != arrival.get ().end (); -} - -std::unique_ptr nano::collect_container_info (block_arrival & block_arrival, std::string const & name) -{ - std::size_t count = 0; - { - nano::lock_guard guard{ block_arrival.mutex }; - count = block_arrival.arrival.size (); - } - - auto sizeof_element = sizeof (decltype (block_arrival.arrival)::value_type); - auto composite = std::make_unique (name); - composite->add_component (std::make_unique (container_info{ "arrival", count, sizeof_element })); - return composite; -} \ No newline at end of file diff --git a/nano/node/block_arrival.hpp b/nano/node/block_arrival.hpp deleted file mode 100644 index 71aa394632..0000000000 --- a/nano/node/block_arrival.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -#include - -namespace nano -{ -class block_arrival_info final -{ -public: - std::chrono::steady_clock::time_point arrival; - nano::block_hash hash; -}; - -// This class tracks blocks that are probably live because they arrived in a UDP packet -// This gives a fairly reliable way to differentiate between blocks being inserted via bootstrap or new, live blocks. -class block_arrival final -{ -public: - // Return `true' to indicated an error if the block has already been inserted - bool add (nano::block_hash const &); - bool recent (nano::block_hash const &); - - // clang-format off - class tag_sequence {}; - class tag_hash {}; - - boost::multi_index_container>, - boost::multi_index::hashed_unique, - boost::multi_index::member>>> - arrival; - // clang-format on - - nano::mutex mutex{ mutex_identifier (mutexes::block_arrival) }; - - static std::size_t constexpr arrival_size_min = 8 * 1024; - static std::chrono::seconds constexpr arrival_time_min = std::chrono::seconds (300); -}; - -std::unique_ptr collect_container_info (block_arrival & block_arrival, std::string const & name); -} \ No newline at end of file diff --git a/nano/node/block_broadcast.cpp b/nano/node/block_broadcast.cpp deleted file mode 100644 index fc996fc0ea..0000000000 --- a/nano/node/block_broadcast.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include - -nano::block_broadcast::block_broadcast (nano::network & network, nano::block_arrival & block_arrival, bool enabled) : - network{ network }, - block_arrival{ block_arrival }, - enabled{ enabled } -{ -} - -void nano::block_broadcast::connect (nano::block_processor & block_processor) -{ - if (!enabled) - { - return; - } - block_processor.processed.add ([this] (auto const & result, auto const & block) { - switch (result.code) - { - case nano::process_result::progress: - observe (block); - break; - default: - break; - } - erase (block); - }); -} - -void nano::block_broadcast::observe (std::shared_ptr block) -{ - nano::unique_lock lock{ mutex }; - auto existing = local.find (block); - auto local_l = existing != local.end (); - lock.unlock (); - if (local_l) - { - // Block created on this node - // Perform more agressive initial flooding - network.flood_block_initial (block); - } - else - { - if (block_arrival.recent (block->hash ())) - { - // Block arrived from realtime traffic, do normal gossip. - network.flood_block (block, nano::transport::buffer_drop_policy::limiter); - } - else - { - // Block arrived from bootstrap - // Don't broadcast blocks we're bootstrapping - } - } -} - -void nano::block_broadcast::set_local (std::shared_ptr block) -{ - if (!enabled) - { - return; - } - nano::lock_guard lock{ mutex }; - local.insert (block); -} - -void nano::block_broadcast::erase (std::shared_ptr block) -{ - if (!enabled) - { - return; - } - nano::lock_guard lock{ mutex }; - local.erase (block); -} diff --git a/nano/node/block_broadcast.hpp b/nano/node/block_broadcast.hpp deleted file mode 100644 index 081d3f2f0b..0000000000 --- a/nano/node/block_broadcast.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace nano -{ -class block_arrival; -class block_processor; -class network; -// This class tracks blocks that originated from this node. -class block_broadcast -{ -public: - block_broadcast (nano::network & network, nano::block_arrival & block_arrival, bool enabled = false); - // Add batch_processed observer to block_processor if enabled - void connect (nano::block_processor & block_processor); - // Mark a block as originating locally - void set_local (std::shared_ptr block); - void erase (std::shared_ptr block); - -private: - // Block_processor observer - void observe (std::shared_ptr block); - - nano::network & network; - nano::block_arrival & block_arrival; - std::unordered_set> local; // Blocks originated on this node - nano::mutex mutex; - bool enabled; -}; -} diff --git a/nano/node/block_publisher.cpp b/nano/node/block_publisher.cpp deleted file mode 100644 index 1cc77e5edb..0000000000 --- a/nano/node/block_publisher.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include - -nano::block_publisher::block_publisher (nano::active_transactions & active) : - active{ active } -{ -} - -void nano::block_publisher::connect (nano::block_processor & block_processor) -{ - block_processor.processed.add ([this] (auto const & result, auto const & block) { - switch (result.code) - { - case nano::process_result::fork: - observe (block); - break; - default: - break; - } - }); -} - -void nano::block_publisher::observe (std::shared_ptr block) -{ - active.publish (block); -} diff --git a/nano/node/block_publisher.hpp b/nano/node/block_publisher.hpp deleted file mode 100644 index 29a2df906b..0000000000 --- a/nano/node/block_publisher.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -namespace nano -{ -class active_transactions; -class block_processor; -class block; - -// This class tracks processed blocks to be published. -class block_publisher -{ -public: - block_publisher (nano::active_transactions & active); - void connect (nano::block_processor & block_processor); - -private: - // Block_processor observer - void observe (std::shared_ptr block); - - nano::active_transactions & active; -}; -} diff --git a/nano/node/blocking_observer.cpp b/nano/node/blocking_observer.cpp deleted file mode 100644 index 339b09b84b..0000000000 --- a/nano/node/blocking_observer.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -void nano::blocking_observer::connect (nano::block_processor & block_processor) -{ - block_processor.processed.add ([this] (auto const & result, auto const & block) { - observe (result, block); - }); -} - -void nano::blocking_observer::stop () -{ - nano::unique_lock lock{ mutex }; - stopped = true; - auto discard = std::move (blocking); - // Signal broken promises outside lock - lock.unlock (); - discard.clear (); // ~promise future_error -} - -void nano::blocking_observer::observe (nano::process_return const & result, std::shared_ptr block) -{ - nano::unique_lock lock{ mutex }; - auto existing = blocking.find (block); - if (existing != blocking.end ()) - { - auto promise = std::move (existing->second); - blocking.erase (existing); - // Signal promise outside of lock - lock.unlock (); - promise.set_value (result); - } -} - -std::future nano::blocking_observer::insert (std::shared_ptr block) -{ - nano::lock_guard lock{ mutex }; - if (stopped) - { - std::promise promise; - return promise.get_future (); // ~promise future_error - } - auto iterator = blocking.emplace (block, std::promise{}); - return iterator->second.get_future (); -} - -bool nano::blocking_observer::exists (std::shared_ptr block) -{ - nano::lock_guard lock{ mutex }; - auto existing = blocking.find (block); - return existing != blocking.end (); -} - -void nano::blocking_observer::erase (std::shared_ptr block) -{ - nano::lock_guard lock{ mutex }; - auto existing = blocking.find (block); - if (existing != blocking.end ()) - { - blocking.erase (existing); - } -} \ No newline at end of file diff --git a/nano/node/blocking_observer.hpp b/nano/node/blocking_observer.hpp deleted file mode 100644 index bd97141224..0000000000 --- a/nano/node/blocking_observer.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -namespace nano -{ -class block; -class block_processor; -// Observer that facilitates a blocking call to block processing which is done asynchronosly by the block_processor -class blocking_observer -{ -public: - void connect (nano::block_processor & block_processor); - // Stop the observer and trigger broken promise exceptions - void stop (); - // Block processor observer - void observe (nano::process_return const & result, std::shared_ptr block); - [[nodiscard]] std::future insert (std::shared_ptr block); - bool exists (std::shared_ptr block); - void erase (std::shared_ptr block); - -private: - std::unordered_multimap, std::promise> blocking; - bool stopped{ false }; - nano::mutex mutex; -}; -} diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index 6d843fea54..3bb23c8ee2 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -1,28 +1,67 @@ +#include #include #include #include #include +#include #include #include +#include + +/* + * block_processor::context + */ + +nano::block_processor::context::context (std::shared_ptr block, nano::block_source source_a) : + block{ block }, + source{ source_a } +{ + debug_assert (source != nano::block_source::unknown); +} + +auto nano::block_processor::context::get_future () -> std::future +{ + return promise.get_future (); +} + +void nano::block_processor::context::set_result (result_t const & result) +{ + promise.set_value (result); +} + +/* + * block_processor + */ + nano::block_processor::block_processor (nano::node & node_a, nano::write_database_queue & write_database_queue_a) : - next_log (std::chrono::steady_clock::now ()), node (node_a), - write_database_queue (write_database_queue_a) + write_database_queue (write_database_queue_a), + next_log (std::chrono::steady_clock::now ()) { batch_processed.add ([this] (auto const & items) { // For every batch item: notify the 'processed' observer. - for (auto const & item : items) + for (auto const & [result, context] : items) { - auto const & [result, block] = item; - processed.notify (result, block); + block_processed.notify (result, context); } }); - blocking.connect (*this); - processing_thread = std::thread ([this] () { +} + +nano::block_processor::~block_processor () +{ + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); +} + +void nano::block_processor::start () +{ + debug_assert (!thread.joinable ()); + + thread = std::thread ([this] () { nano::thread_role::set (nano::thread_role::name::block_processing); - this->process_blocks (); + run (); }); } @@ -33,19 +72,10 @@ void nano::block_processor::stop () stopped = true; } condition.notify_all (); - blocking.stop (); - nano::join_or_pass (processing_thread); -} - -void nano::block_processor::flush () -{ - flushing = true; - nano::unique_lock lock{ mutex }; - while (!stopped && (have_blocks () || active)) + if (thread.joinable ()) { - condition.wait (lock); + thread.join (); } - flushing = false; } std::size_t nano::block_processor::size () @@ -64,7 +94,7 @@ bool nano::block_processor::half_full () return size () >= node.flags.block_processor_full_size / 2; } -void nano::block_processor::add (std::shared_ptr const & block) +void nano::block_processor::add (std::shared_ptr const & block, block_source const source) { if (full ()) { @@ -76,33 +106,50 @@ void nano::block_processor::add (std::shared_ptr const & block) node.stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::insufficient_work); return; } - add_impl (block); - return; + + node.stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::process); + node.logger.debug (nano::log::type::blockprocessor, "Processing block (async): {} (source: {})", block->hash ().to_string (), to_string (source)); + + add_impl (context{ block, source }); } -std::optional nano::block_processor::add_blocking (std::shared_ptr const & block) +std::optional nano::block_processor::add_blocking (std::shared_ptr const & block, block_source const source) { - auto future = blocking.insert (block); - add_impl (block); - condition.notify_all (); - std::optional result; + node.stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::process_blocking); + node.logger.debug (nano::log::type::blockprocessor, "Processing block (blocking): {} (source: {})", block->hash ().to_string (), to_string (source)); + + context ctx{ block, source }; + auto future = ctx.get_future (); + add_impl (std::move (ctx)); + try { auto status = future.wait_for (node.config.block_process_timeout); debug_assert (status != std::future_status::deferred); if (status == std::future_status::ready) { - result = future.get (); - } - else - { - blocking.erase (block); + return future.get (); } } catch (std::future_error const &) { + node.stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::process_blocking_timeout); + node.logger.error (nano::log::type::blockprocessor, "Timeout processing block: {}", block->hash ().to_string ()); } - return result; + + return std::nullopt; +} + +void nano::block_processor::force (std::shared_ptr const & block_a) +{ + node.stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::force); + node.logger.debug (nano::log::type::blockprocessor, "Forcing block: {}", block_a->hash ().to_string ()); + + { + nano::lock_guard lock{ mutex }; + forced.emplace_back (context{ block_a, block_source::forced }); + } + condition.notify_all (); } void nano::block_processor::rollback_competitor (store::write_transaction const & transaction, nano::block const & block) @@ -112,23 +159,25 @@ void nano::block_processor::rollback_competitor (store::write_transaction const if (successor != nullptr && successor->hash () != hash) { // Replace our block with the winner and roll back any dependent blocks - if (node.config.logging.ledger_rollback_logging ()) - { - node.logger.always_log (boost::str (boost::format ("Rolling back %1% and replacing with %2%") % successor->hash ().to_string () % hash.to_string ())); - } + node.logger.debug (nano::log::type::blockprocessor, "Rolling back: {} and replacing with: {}", successor->hash ().to_string (), hash.to_string ()); + std::vector> rollback_list; if (node.ledger.rollback (transaction, successor->hash (), rollback_list)) { node.stats.inc (nano::stat::type::ledger, nano::stat::detail::rollback_failed); - node.logger.always_log (nano::severity_level::error, boost::str (boost::format ("Failed to roll back %1% because it or a successor was confirmed") % successor->hash ().to_string ())); + node.logger.error (nano::log::type::blockprocessor, "Failed to roll back: {} because it or a successor was confirmed", successor->hash ().to_string ()); } - else if (node.config.logging.ledger_rollback_logging ()) + else { - node.logger.always_log (boost::str (boost::format ("%1% blocks rolled back") % rollback_list.size ())); + node.stats.inc (nano::stat::type::ledger, nano::stat::detail::rollback); + node.logger.debug (nano::log::type::blockprocessor, "Blocks rolled back: {}", rollback_list.size ()); } + // Deleting from votes cache, stop active transaction for (auto & i : rollback_list) { + rolled_back.notify (i); + node.history.erase (i->root ()); // Stop all rolled back active transactions except initial if (i->hash () != successor->hash ()) @@ -139,28 +188,27 @@ void nano::block_processor::rollback_competitor (store::write_transaction const } } -void nano::block_processor::force (std::shared_ptr const & block_a) -{ - { - nano::lock_guard lock{ mutex }; - forced.push_back (block_a); - } - condition.notify_all (); -} - -void nano::block_processor::process_blocks () +void nano::block_processor::run () { nano::unique_lock lock{ mutex }; while (!stopped) { if (have_blocks_ready ()) { - active = true; lock.unlock (); + auto processed = process_batch (lock); + debug_assert (!lock.owns_lock ()); + + // Set results for futures when not holding the lock + for (auto & [result, context] : processed) + { + context.set_result (result); + } + batch_processed.notify (processed); + lock.lock (); - active = false; } else { @@ -176,7 +224,7 @@ bool nano::block_processor::should_log () auto now (std::chrono::steady_clock::now ()); if (next_log < now) { - next_log = now + (node.config.logging.timing_logging () ? std::chrono::seconds (2) : std::chrono::seconds (15)); + next_log = now + std::chrono::seconds (15); result = true; } return result; @@ -194,235 +242,221 @@ bool nano::block_processor::have_blocks () return have_blocks_ready (); } -void nano::block_processor::add_impl (std::shared_ptr block) +void nano::block_processor::add_impl (context ctx) { + release_assert (ctx.source != nano::block_source::forced); { nano::lock_guard guard{ mutex }; - blocks.emplace_back (block); + blocks.emplace_back (std::move (ctx)); } condition.notify_all (); } -auto nano::block_processor::process_batch (nano::unique_lock & lock_a) -> std::deque +auto nano::block_processor::next () -> context { - std::deque processed; + debug_assert (!mutex.try_lock ()); + debug_assert (!blocks.empty () || !forced.empty ()); // This should be checked before calling next + + if (!forced.empty ()) + { + auto entry = std::move (forced.front ()); + release_assert (entry.source == nano::block_source::forced); + forced.pop_front (); + return entry; + } + + if (!blocks.empty ()) + { + auto entry = std::move (blocks.front ()); + release_assert (entry.source != nano::block_source::forced); + blocks.pop_front (); + return entry; + } + + release_assert (false, "next() called when no blocks are ready"); +} + +auto nano::block_processor::process_batch (nano::unique_lock & lock_a) -> processed_batch_t +{ + processed_batch_t processed; + auto scoped_write_guard = write_database_queue.wait (nano::writer::process_batch); auto transaction (node.store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending })); nano::timer timer_l; + lock_a.lock (); + timer_l.start (); // Processing blocks unsigned number_of_blocks_processed (0), number_of_forced_processed (0); auto deadline_reached = [&timer_l, deadline = node.config.block_processor_batch_max_time] { return timer_l.after_deadline (deadline); }; auto processor_batch_reached = [&number_of_blocks_processed, max = node.flags.block_processor_batch_size] { return number_of_blocks_processed >= max; }; auto store_batch_reached = [&number_of_blocks_processed, max = node.store.max_block_write_batch_num ()] { return number_of_blocks_processed >= max; }; + while (have_blocks_ready () && (!deadline_reached () || !processor_batch_reached ()) && !store_batch_reached ()) { + // TODO: Cleaner periodical logging if ((blocks.size () + forced.size () > 64) && should_log ()) { - node.logger.always_log (boost::str (boost::format ("%1% blocks (+ %2% forced) in processing queue") % blocks.size () % forced.size ())); - } - std::shared_ptr block; - nano::block_hash hash (0); - bool force (false); - if (forced.empty ()) - { - block = blocks.front (); - blocks.pop_front (); - hash = block->hash (); - } - else - { - block = forced.front (); - forced.pop_front (); - hash = block->hash (); - force = true; - number_of_forced_processed++; + node.logger.debug (nano::log::type::blockprocessor, "{} blocks (+ {} forced) in processing queue", blocks.size (), forced.size ()); } + + auto ctx = next (); + auto const hash = ctx.block->hash (); + bool const force = ctx.source == nano::block_source::forced; + lock_a.unlock (); + if (force) { - rollback_competitor (transaction, *block); + number_of_forced_processed++; + rollback_competitor (transaction, *ctx.block); } + number_of_blocks_processed++; - auto result = process_one (transaction, block, force); - processed.emplace_back (result, block); + + auto result = process_one (transaction, ctx, force); + processed.emplace_back (result, std::move (ctx)); + lock_a.lock (); } + lock_a.unlock (); - if (node.config.logging.timing_logging () && number_of_blocks_processed != 0 && timer_l.stop () > std::chrono::milliseconds (100)) + if (number_of_blocks_processed != 0 && timer_l.stop () > std::chrono::milliseconds (100)) { - node.logger.always_log (boost::str (boost::format ("Processed %1% blocks (%2% blocks were forced) in %3% %4%") % number_of_blocks_processed % number_of_forced_processed % timer_l.value ().count () % timer_l.unit ())); + node.logger.debug (nano::log::type::blockprocessor, "Processed {} blocks ({} forced) in {} {}", number_of_blocks_processed, number_of_forced_processed, timer_l.value ().count (), timer_l.unit ()); } + return processed; } -nano::process_return nano::block_processor::process_one (store::write_transaction const & transaction_a, std::shared_ptr block, bool const forced_a) +nano::block_status nano::block_processor::process_one (store::write_transaction const & transaction_a, context const & context, bool const forced_a) { - nano::process_return result; - auto hash (block->hash ()); - result = node.ledger.process (transaction_a, *block); - switch (result.code) + auto block = context.block; + auto const hash = block->hash (); + nano::block_status result = node.ledger.process (transaction_a, block); + + node.stats.inc (nano::stat::type::blockprocessor_result, to_stat_detail (result)); + node.stats.inc (nano::stat::type::blockprocessor_source, to_stat_detail (context.source)); + node.logger.trace (nano::log::type::blockprocessor, nano::log::detail::block_processed, + nano::log::arg{ "result", result }, + nano::log::arg{ "source", context.source }, + nano::log::arg{ "arrival", nano::log::microseconds (context.arrival) }, + nano::log::arg{ "forced", forced_a }, + nano::log::arg{ "block", block }); + + switch (result) { - case nano::process_result::progress: + case nano::block_status::progress: { - if (node.config.logging.ledger_logging ()) - { - std::string block_string; - block->serialize_json (block_string, node.config.logging.single_line_record ()); - node.logger.try_log (boost::str (boost::format ("Processing block %1%: %2%") % hash.to_string () % block_string)); - } queue_unchecked (transaction_a, hash); /* For send blocks check epoch open unchecked (gap pending). For state blocks check only send subtype and only if block epoch is not last epoch. If epoch is last, then pending entry shouldn't trigger same epoch open block for destination account. */ - if (block->type () == nano::block_type::send || (block->type () == nano::block_type::state && block->sideband ().details.is_send && std::underlying_type_t (block->sideband ().details.epoch) < std::underlying_type_t (nano::epoch::max))) + if (block->type () == nano::block_type::send || (block->type () == nano::block_type::state && block->is_send () && std::underlying_type_t (block->sideband ().details.epoch) < std::underlying_type_t (nano::epoch::max))) { /* block->destination () for legacy send blocks block->link () for state blocks (send subtype) */ - queue_unchecked (transaction_a, block->destination ().is_zero () ? block->link () : block->destination ()); + queue_unchecked (transaction_a, block->destination ()); } break; } - case nano::process_result::gap_previous: + case nano::block_status::gap_previous: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Gap previous for: %1%") % hash.to_string ())); - } node.unchecked.put (block->previous (), block); node.stats.inc (nano::stat::type::ledger, nano::stat::detail::gap_previous); break; } - case nano::process_result::gap_source: + case nano::block_status::gap_source: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Gap source for: %1%") % hash.to_string ())); - } - node.unchecked.put (node.ledger.block_source (transaction_a, *block), block); + release_assert (block->source_field () || block->link_field ()); + node.unchecked.put (block->source_field ().value_or (block->link_field ().value_or (0).as_block_hash ()), block); node.stats.inc (nano::stat::type::ledger, nano::stat::detail::gap_source); break; } - case nano::process_result::gap_epoch_open_pending: + case nano::block_status::gap_epoch_open_pending: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Gap pending entries for epoch open: %1%") % hash.to_string ())); - } - node.unchecked.put (block->account (), block); // Specific unchecked key starting with epoch open block account public key + node.unchecked.put (block->account_field ().value_or (0), block); // Specific unchecked key starting with epoch open block account public key node.stats.inc (nano::stat::type::ledger, nano::stat::detail::gap_source); break; } - case nano::process_result::old: + case nano::block_status::old: { - if (node.config.logging.ledger_duplicate_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Old for: %1%") % hash.to_string ())); - } node.stats.inc (nano::stat::type::ledger, nano::stat::detail::old); break; } - case nano::process_result::bad_signature: + case nano::block_status::bad_signature: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Bad signature for: %1%") % hash.to_string ())); - } break; } - case nano::process_result::negative_spend: + case nano::block_status::negative_spend: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Negative spend for: %1%") % hash.to_string ())); - } break; } - case nano::process_result::unreceivable: + case nano::block_status::unreceivable: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Unreceivable for: %1%") % hash.to_string ())); - } break; } - case nano::process_result::fork: + case nano::block_status::fork: { node.stats.inc (nano::stat::type::ledger, nano::stat::detail::fork); - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Fork for: %1% root: %2%") % hash.to_string () % block->root ().to_string ())); - } break; } - case nano::process_result::opened_burn_account: + case nano::block_status::opened_burn_account: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Rejecting open block for burn account: %1%") % hash.to_string ())); - } break; } - case nano::process_result::balance_mismatch: + case nano::block_status::balance_mismatch: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Balance mismatch for: %1%") % hash.to_string ())); - } break; } - case nano::process_result::representative_mismatch: + case nano::block_status::representative_mismatch: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Representative mismatch for: %1%") % hash.to_string ())); - } break; } - case nano::process_result::block_position: + case nano::block_status::block_position: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Block %1% cannot follow predecessor %2%") % hash.to_string () % block->previous ().to_string ())); - } break; } - case nano::process_result::insufficient_work: + case nano::block_status::insufficient_work: { - if (node.config.logging.ledger_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Insufficient work for %1% : %2% (difficulty %3%)") % hash.to_string () % nano::to_string_hex (block->block_work ()) % nano::to_string_hex (node.network_params.work.difficulty (*block)))); - } break; } } - - node.stats.inc (nano::stat::type::blockprocessor, nano::to_stat_detail (result.code)); - return result; } void nano::block_processor::queue_unchecked (store::write_transaction const & transaction_a, nano::hash_or_account const & hash_or_account_a) { node.unchecked.trigger (hash_or_account_a); - node.gap_cache.erase (hash_or_account_a.hash); } -std::unique_ptr nano::collect_container_info (block_processor & block_processor, std::string const & name) +std::unique_ptr nano::block_processor::collect_container_info (std::string const & name) { std::size_t blocks_count; std::size_t forced_count; { - nano::lock_guard guard{ block_processor.mutex }; - blocks_count = block_processor.blocks.size (); - forced_count = block_processor.forced.size (); + nano::lock_guard guard{ mutex }; + blocks_count = blocks.size (); + forced_count = forced.size (); } auto composite = std::make_unique (name); - composite->add_component (std::make_unique (container_info{ "blocks", blocks_count, sizeof (decltype (block_processor.blocks)::value_type) })); - composite->add_component (std::make_unique (container_info{ "forced", forced_count, sizeof (decltype (block_processor.forced)::value_type) })); + composite->add_component (std::make_unique (container_info{ "blocks", blocks_count, sizeof (decltype (blocks)::value_type) })); + composite->add_component (std::make_unique (container_info{ "forced", forced_count, sizeof (decltype (forced)::value_type) })); return composite; } + +std::string_view nano::to_string (nano::block_source source) +{ + return magic_enum::enum_name (source); +} + +nano::stat::detail nano::to_stat_detail (nano::block_source type) +{ + auto value = magic_enum::enum_cast (magic_enum::enum_name (type)); + debug_assert (value); + return value.value_or (nano::stat::detail{}); +} diff --git a/nano/node/blockprocessor.hpp b/nano/node/blockprocessor.hpp index 5e87663897..0d020e8b16 100644 --- a/nano/node/blockprocessor.hpp +++ b/nano/node/blockprocessor.hpp @@ -1,14 +1,21 @@ #pragma once -#include -#include +#include #include #include #include #include +#include #include +namespace nano +{ +class block; +class node; +class write_database_queue; +} + namespace nano::store { class write_transaction; @@ -16,8 +23,20 @@ class write_transaction; namespace nano { -class node; -class write_database_queue; + +enum class block_source +{ + unknown = 0, + live, + bootstrap, + bootstrap_legacy, + unchecked, + local, + forced, +}; + +std::string_view to_string (block_source); +nano::stat::detail to_stat_detail (block_source); /** * Processing blocks is a potentially long IO operation. @@ -25,52 +44,80 @@ class write_database_queue; */ class block_processor final { +public: // Context + class context + { + public: + context (std::shared_ptr block, block_source source); + + std::shared_ptr const block; + block_source const source; + std::chrono::steady_clock::time_point const arrival{ std::chrono::steady_clock::now () }; + + public: + using result_t = nano::block_status; + std::future get_future (); + + private: + void set_result (result_t const &); + std::promise promise; + + friend class block_processor; + }; + public: - explicit block_processor (nano::node &, nano::write_database_queue &); + block_processor (nano::node &, nano::write_database_queue &); + ~block_processor (); + + void start (); void stop (); - void flush (); + std::size_t size (); bool full (); bool half_full (); - void add (std::shared_ptr const &); - std::optional add_blocking (std::shared_ptr const & block); + void add (std::shared_ptr const &, block_source = block_source::live); + std::optional add_blocking (std::shared_ptr const & block, block_source); void force (std::shared_ptr const &); bool should_log (); bool have_blocks_ready (); bool have_blocks (); - void process_blocks (); + + std::unique_ptr collect_container_info (std::string const & name); std::atomic flushing{ false }; public: // Events - using processed_t = std::pair>; - nano::observer_set> processed; + using processed_t = std::tuple; + using processed_batch_t = std::deque; - // The batch observer feeds the processed obsever - nano::observer_set const &> batch_processed; - -private: - blocking_observer blocking; + // The batch observer feeds the processed observer + nano::observer_set block_processed; + nano::observer_set batch_processed; + nano::observer_set const &> rolled_back; private: + void run (); // Roll back block in the ledger that conflicts with 'block' - void rollback_competitor (store::write_transaction const & transaction, nano::block const & block); - nano::process_return process_one (store::write_transaction const &, std::shared_ptr block, bool const = false); + void rollback_competitor (store::write_transaction const &, nano::block const & block); + nano::block_status process_one (store::write_transaction const &, context const &, bool forced = false); void queue_unchecked (store::write_transaction const &, nano::hash_or_account const &); - std::deque process_batch (nano::unique_lock &); - void add_impl (std::shared_ptr block); - bool stopped{ false }; - bool active{ false }; - std::chrono::steady_clock::time_point next_log; - std::deque> blocks; - std::deque> forced; - nano::condition_variable condition; + processed_batch_t process_batch (nano::unique_lock &); + context next (); + void add_impl (context); + +private: // Dependencies nano::node & node; nano::write_database_queue & write_database_queue; - nano::mutex mutex{ mutex_identifier (mutexes::block_processor) }; - std::thread processing_thread; - friend std::unique_ptr collect_container_info (block_processor & block_processor, std::string const & name); +private: + std::deque blocks; + std::deque forced; + + std::chrono::steady_clock::time_point next_log; + + bool stopped{ false }; + nano::condition_variable condition; + nano::mutex mutex{ mutex_identifier (mutexes::block_processor) }; + std::thread thread; }; -std::unique_ptr collect_container_info (block_processor & block_processor, std::string const & name); } diff --git a/nano/node/bootstrap/block_deserializer.hpp b/nano/node/bootstrap/block_deserializer.hpp index 9e53aa7903..98499200de 100644 --- a/nano/node/bootstrap/block_deserializer.hpp +++ b/nano/node/bootstrap/block_deserializer.hpp @@ -1,6 +1,8 @@ #pragma once -#include +#include + +#include #include #include diff --git a/nano/node/bootstrap/bootstrap.cpp b/nano/node/bootstrap/bootstrap.cpp index 48cb46b790..451b93aaea 100644 --- a/nano/node/bootstrap/bootstrap.cpp +++ b/nano/node/bootstrap/bootstrap.cpp @@ -165,7 +165,7 @@ bool nano::bootstrap_initiator::in_progress () return !attempts_list.empty (); } -void nano::bootstrap_initiator::block_processed (store::transaction const & tx, nano::process_return const & result, nano::block const & block) +void nano::bootstrap_initiator::block_processed (store::transaction const & tx, nano::block_status const & result, nano::block const & block) { nano::lock_guard lock{ mutex }; for (auto & i : attempts_list) diff --git a/nano/node/bootstrap/bootstrap.hpp b/nano/node/bootstrap/bootstrap.hpp index f9100da023..6d2052fc8f 100644 --- a/nano/node/bootstrap/bootstrap.hpp +++ b/nano/node/bootstrap/bootstrap.hpp @@ -105,7 +105,7 @@ class bootstrap_initiator final void notify_listeners (bool); void add_observer (std::function const &); bool in_progress (); - void block_processed (store::transaction const & tx, nano::process_return const & result, nano::block const & block); + void block_processed (store::transaction const & tx, nano::block_status const & result, nano::block const & block); std::shared_ptr connections; std::shared_ptr new_attempt (); bool has_new_attempts (); diff --git a/nano/node/bootstrap/bootstrap_attempt.cpp b/nano/node/bootstrap/bootstrap_attempt.cpp index 4656ad5f4f..032cdd3b5e 100644 --- a/nano/node/bootstrap/bootstrap_attempt.cpp +++ b/nano/node/bootstrap/bootstrap_attempt.cpp @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#include #include @@ -20,7 +22,8 @@ nano::bootstrap_attempt::bootstrap_attempt (std::shared_ptr const & id = nano::hardened_constants::get ().random_128.to_string (); } - node_a->logger.always_log (boost::str (boost::format ("Starting %1% bootstrap attempt with ID %2%") % mode_text () % id)); + node_a->logger.debug (nano::log::type::bootstrap, "Starting bootstrap attempt with ID: {} (mode: {})", mode_text (), id); + node_a->bootstrap_initiator.notify_listeners (true); if (node_a->websocket.server) { @@ -36,7 +39,9 @@ nano::bootstrap_attempt::~bootstrap_attempt () { return; } - node->logger.always_log (boost::str (boost::format ("Exiting %1% bootstrap attempt with ID %2%") % mode_text () % id)); + + node->logger.debug (nano::log::type::bootstrap, "Exiting bootstrap attempt with ID: {} (mode: {})", mode_text (), id); + node->bootstrap_initiator.notify_listeners (false); if (node->websocket.server) { @@ -130,11 +135,11 @@ bool nano::bootstrap_attempt::process_block (std::shared_ptr const } else { - node_l->block_processor.add (block_a); + node_l->block_processor.add (block_a, nano::block_source::bootstrap_legacy); } return stop_pull; } -void nano::bootstrap_attempt::block_processed (store::transaction const & tx, nano::process_return const & result, nano::block const & block) +void nano::bootstrap_attempt::block_processed (store::transaction const & tx, nano::block_status const & result, nano::block const & block) { } diff --git a/nano/node/bootstrap/bootstrap_attempt.hpp b/nano/node/bootstrap/bootstrap_attempt.hpp index fa9ed15e61..ea64fe9fd0 100644 --- a/nano/node/bootstrap/bootstrap_attempt.hpp +++ b/nano/node/bootstrap/bootstrap_attempt.hpp @@ -34,7 +34,7 @@ class bootstrap_attempt : public std::enable_shared_from_this char const * mode_text (); virtual bool process_block (std::shared_ptr const &, nano::account const &, uint64_t, nano::bulk_pull::count_t, bool, unsigned); virtual void get_information (boost::property_tree::ptree &) = 0; - virtual void block_processed (store::transaction const & tx, nano::process_return const & result, nano::block const & block); + virtual void block_processed (store::transaction const & tx, nano::block_status const & result, nano::block const & block); nano::mutex next_log_mutex; std::chrono::steady_clock::time_point next_log{ std::chrono::steady_clock::now () }; std::atomic pulling{ 0 }; diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.cpp b/nano/node/bootstrap/bootstrap_bulk_pull.cpp index 5c0daa4602..a1fe5b8ec2 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,7 @@ #include #include #include +#include #include @@ -46,10 +48,8 @@ nano::bulk_pull_client::~bulk_pull_client () } pull.processed += pull_blocks - unexpected_count; node->bootstrap_initiator.connections->requeue_pull (pull, network_error); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Bulk pull end block is not expected %1% for account %2% or head block %3%") % pull.end.to_string () % pull.account_or_head.to_account () % pull.account_or_head.to_string ())); - } + + node->logger.debug (nano::log::type::bulk_pull_client, "Bulk pull end block is not expected {} for account {} or head block {}", pull.end.to_string (), pull.account_or_head.to_account (), pull.account_or_head.to_string ()); } else { @@ -82,14 +82,15 @@ void nano::bulk_pull_client::request () req.count = pull.count; req.set_count_present (pull.count != 0); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Requesting account %1% or head block %2% from %3%. %4% accounts in queue") % pull.account_or_head.to_account () % pull.account_or_head.to_string () % connection->channel->to_string () % attempt->pulling)); - } - else if (node->config.logging.network_logging () && attempt->should_log ()) + node->logger.trace (nano::log::type::bulk_pull_client, nano::log::detail::requesting_account_or_head, + nano::log::arg{ "account_or_head", pull.account_or_head }, + nano::log::arg{ "channel", connection->channel }); + + if (attempt->should_log ()) { - node->logger.always_log (boost::str (boost::format ("%1% accounts in pull queue") % attempt->pulling)); + node->logger.debug (nano::log::type::bulk_pull_client, "Accounts in pull queue: {}", attempt->pulling.load ()); } + auto this_l (shared_from_this ()); connection->channel->send ( req, [this_l] (boost::system::error_code const & ec, std::size_t size_a) { @@ -104,10 +105,7 @@ void nano::bulk_pull_client::request () } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error sending bulk pull request to %1%: to %2%") % ec.message () % this_l->connection->channel->to_string ())); - } + node->logger.debug (nano::log::type::bulk_pull_client, "Error sending bulk pull request to: {} ({})", this_l->connection->channel->to_string (), ec.message ()); node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_request_failure, nano::stat::dir::in); } }, @@ -168,24 +166,18 @@ void nano::bulk_pull_client::received_block (boost::system::error_code ec, std:: } if (node->network_params.work.validate_entry (*block)) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Insufficient work for bulk pull block: %1%") % block->hash ().to_string ())); - } - node->stats.inc_detail_only (nano::stat::type::error, nano::stat::detail::insufficient_work); + node->logger.debug (nano::log::type::bulk_pull_client, "Insufficient work for bulk pull block: {}", block->hash ().to_string ()); + node->stats.inc (nano::stat::type::error, nano::stat::detail::insufficient_work); return; } auto hash = block->hash (); - if (node->config.logging.bulk_pull_logging ()) - { - std::string block_l; - block->serialize_json (block_l, node->config.logging.single_line_record ()); - node->logger.try_log (boost::str (boost::format ("Pulled block %1% %2%") % hash.to_string () % block_l)); - } + + node->logger.trace (nano::log::type::bulk_pull_client, nano::log::detail::pulled_block, nano::log::arg{ "block", block }); + // Is block expected? bool block_expected (false); // Unconfirmed head is used only for lazy destinations if legacy bootstrap is not available, see nano::bootstrap_attempt::lazy_destinations_increment (...) - bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account () == pull.account_or_head.as_account ()); + bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account_field () == pull.account_or_head.as_account ()); if (hash == expected || unconfirmed_account_head) { expected = block->previous (); @@ -197,7 +189,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code ec, std:: } if (pull_blocks == 0 && block_expected) { - known_account = block->account (); + known_account = block->account_field ().value_or (0); } if (connection->block_count++ == 0) { @@ -247,14 +239,16 @@ void nano::bulk_pull_account_client::request () req.account = account; req.minimum_amount = node->config.receive_minimum; req.flags = nano::bulk_pull_account_flags::pending_hash_and_amount; - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Requesting pending for account %1% from %2%. %3% accounts in queue") % req.account.to_account () % connection->channel->to_string () % attempt->wallet_size ())); - } - else if (node->config.logging.network_logging () && attempt->should_log ()) + + node->logger.trace (nano::log::type::bulk_pull_account_client, nano::log::detail::requesting_pending, + nano::log::arg{ "account", req.account.to_account () }, // TODO: Convert to lazy eval + nano::log::arg{ "connection", connection->channel }); + + if (attempt->should_log ()) { - node->logger.always_log (boost::str (boost::format ("%1% accounts in pull queue") % attempt->wallet_size ())); + node->logger.debug (nano::log::type::bulk_pull_account_client, "Accounts in pull queue: {}", attempt->wallet_size ()); } + auto this_l (shared_from_this ()); connection->channel->send ( req, [this_l] (boost::system::error_code const & ec, std::size_t size_a) { @@ -269,12 +263,10 @@ void nano::bulk_pull_account_client::request () } else { - this_l->attempt->requeue_pending (this_l->account); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error starting bulk pull request to %1%: to %2%") % ec.message () % this_l->connection->channel->to_string ())); - } + node->logger.debug (nano::log::type::bulk_pull_account_client, "Error starting bulk pull request to: {} ({})", this_l->connection->channel->to_string (), ec.message ()); node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_error_starting_request, nano::stat::dir::in); + + this_l->attempt->requeue_pending (this_l->account); } }, nano::transport::buffer_drop_policy::no_limiter_drop); @@ -334,20 +326,16 @@ void nano::bulk_pull_account_client::receive_pending () } else { + node->logger.debug (nano::log::type::bulk_pull_account_client, "Error while receiving bulk pull account frontier: {}", ec.message ()); + this_l->attempt->requeue_pending (this_l->account); - if (node->config.logging.network_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error while receiving bulk pull account frontier %1%") % ec.message ())); - } } } else { + node->logger.debug (nano::log::type::bulk_pull_account_client, "Invalid size: Expected {}, got: {}", size_l, size_a); + this_l->attempt->requeue_pending (this_l->account); - if (node->config.logging.network_message_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Invalid size: expected %1%, got %2%") % size_l % size_a)); - } } }); } @@ -377,21 +365,16 @@ void nano::bulk_pull_server::set_current_end () include_start = false; debug_assert (request != nullptr); auto transaction (node->store.tx_begin_read ()); - if (!node->store.block.exists (transaction, request->end)) + if (!node->ledger.block_exists (transaction, request->end)) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Bulk pull end block doesn't exist: %1%, sending everything") % request->end.to_string ())); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Bulk pull end block doesn't exist: {}, sending everything", request->end.to_string ()); + request->end.clear (); } - if (node->store.block.exists (transaction, request->start.as_block_hash ())) + if (node->ledger.block_exists (transaction, request->start.as_block_hash ())) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Bulk pull request for block hash: %1%") % request->start.to_string ())); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Bulk pull request for block hash: {}", request->start.to_string ()); current = ascending () ? node->store.block.successor (transaction, request->start.as_block_hash ()) : request->start.as_block_hash (); include_start = true; @@ -401,10 +384,8 @@ void nano::bulk_pull_server::set_current_end () auto info = node->ledger.account_info (transaction, request->start.as_account ()); if (!info) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Request for unknown account: %1%") % request->start.to_account ())); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Request for unknown account: {}", request->start.to_account ()); + current = request->end; } else @@ -415,10 +396,8 @@ void nano::bulk_pull_server::set_current_end () auto account (node->ledger.account (transaction, request->end)); if (account != request->start.as_account ()) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Request for block that is not on account chain: %1% not on %2%") % request->end.to_string () % request->start.to_account ())); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Request for block that is not on account chain: {} not on {}", request->end.to_string (), request->start.to_account ()); + current = request->end; } } @@ -446,15 +425,16 @@ void nano::bulk_pull_server::send_next () auto block = get_next (); if (block != nullptr) { + node->logger.trace (nano::log::type::bulk_pull_server, nano::log::detail::sending_block, + nano::log::arg{ "block", block }, + nano::log::arg{ "socket", connection->socket }); + std::vector send_buffer; { nano::vectorstream stream (send_buffer); nano::serialize_block (stream, *block); } - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Sending block: %1%") % block->hash ().to_string ())); - } + connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l = shared_from_this ()] (boost::system::error_code const & ec, std::size_t size_a) { this_l->sent_action (ec, size_a); }); @@ -556,10 +536,7 @@ void nano::bulk_pull_server::sent_action (boost::system::error_code const & ec, } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Unable to bulk send block: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Unable to bulk send block: {}", ec.message ()); } } @@ -572,10 +549,9 @@ void nano::bulk_pull_server::send_finished () } nano::shared_const_buffer send_buffer (static_cast (nano::block_type::not_a_block)); auto this_l (shared_from_this ()); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Bulk sending finished"); - } + + node->logger.debug (nano::log::type::bulk_pull_server, "Bulk sending finished"); + connection->socket->async_write (send_buffer, [this_l] (boost::system::error_code const & ec, std::size_t size_a) { this_l->no_block_sent (ec, size_a); }); @@ -595,10 +571,7 @@ void nano::bulk_pull_server::no_block_sent (boost::system::error_code const & ec } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Unable to send not-a-block"); - } + node->logger.debug (nano::log::type::bulk_pull_server, "Unable to bulk send not-a-block: {}", ec.message ()); } } @@ -650,13 +623,9 @@ void nano::bulk_pull_account_server::set_params () } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Invalid bulk_pull_account flags supplied %1%") % static_cast (request->flags))); - } + node->logger.debug (nano::log::type::bulk_pull_account_server, "Invalid bulk_pull_account flags supplied: {}", static_cast (request->flags)); invalid_request = true; - return; } @@ -728,24 +697,18 @@ void nano::bulk_pull_account_server::send_next_block () std::vector send_buffer; if (pending_address_only) { - nano::vectorstream output_stream (send_buffer); - - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Sending address: %1%") % block_info->source.to_string ())); - } + node->logger.trace (nano::log::type::bulk_pull_account_server, nano::log::detail::sending_pending, + nano::log::arg{ "pending", block_info->source }); + nano::vectorstream output_stream (send_buffer); write (output_stream, block_info->source.bytes); } else { - nano::vectorstream output_stream (send_buffer); - - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Sending block: %1%") % block_info_key->hash.to_string ())); - } + node->logger.trace (nano::log::type::bulk_pull_account_server, nano::log::detail::sending_block, + nano::log::arg{ "block", block_info_key->hash }); + nano::vectorstream output_stream (send_buffer); write (output_stream, block_info_key->hash.bytes); write (output_stream, block_info->amount.bytes); @@ -768,10 +731,7 @@ void nano::bulk_pull_account_server::send_next_block () /* * Otherwise, finalize the connection */ - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Done sending blocks"))); - } + node->logger.debug (nano::log::type::bulk_pull_account_server, "Done sending blocks"); send_finished (); } @@ -876,10 +836,7 @@ void nano::bulk_pull_account_server::sent_action (boost::system::error_code cons } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Unable to bulk send block: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::bulk_pull_account_server, "Unable to bulk send block: {}", ec.message ()); } } @@ -916,13 +873,9 @@ void nano::bulk_pull_account_server::send_finished () } } - auto this_l (shared_from_this ()); - - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Bulk sending for an account finished"); - } + node->logger.debug (nano::log::type::bulk_pull_account_server, "Bulk sending for an account finished"); + auto this_l (shared_from_this ()); connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l] (boost::system::error_code const & ec, std::size_t size_a) { this_l->complete (ec, size_a); }); @@ -957,10 +910,7 @@ void nano::bulk_pull_account_server::complete (boost::system::error_code const & } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Unable to pending-as-zero"); - } + node->logger.debug (nano::log::type::bulk_pull_account_server, "Unable to pending-as-zero: {}", ec.message ()); } } diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.hpp b/nano/node/bootstrap/bootstrap_bulk_pull.hpp index b84a184428..a3e901e666 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.hpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.hpp @@ -2,6 +2,7 @@ #include #include +#include #include diff --git a/nano/node/bootstrap/bootstrap_bulk_push.cpp b/nano/node/bootstrap/bootstrap_bulk_push.cpp index dd1fc76f3c..8a1e81118d 100644 --- a/nano/node/bootstrap/bootstrap_bulk_push.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_push.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -38,10 +39,7 @@ void nano::bulk_push_client::start () } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Unable to send bulk_push request: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::bulk_push_client, "Unable to send bulk push request: {}", ec.message ()); } }, nano::transport::buffer_drop_policy::no_limiter_drop); @@ -71,10 +69,7 @@ void nano::bulk_push_client::push () } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Bulk pushing range ", current_target.first.to_string (), " down to ", current_target.second.to_string ()); - } + node->logger.debug (nano::log::type::bulk_push_client, "Bulk pushing range: [{}:{}]", current_target.first.to_string (), current_target.second.to_string ()); } } } @@ -124,10 +119,7 @@ void nano::bulk_push_client::push_block (nano::block const & block_a) } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error sending block during bulk push: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::bulk_push_client, "Error sending block during bulk push: {}", ec.message ()); } }); } @@ -171,10 +163,7 @@ void nano::bulk_push_server::receive () } if (node->bootstrap_initiator.in_progress ()) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Aborting bulk_push because a bootstrap attempt is in progress"); - } + node->logger.debug (nano::log::type::bulk_push_server, "Aborting bulk push because a bootstrap attempt is in progress"); } else { @@ -191,10 +180,7 @@ void nano::bulk_push_server::receive () } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error receiving block type: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::bulk_push_server, "Error receiving block type: {}", ec.message ()); } }); } @@ -258,10 +244,7 @@ void nano::bulk_push_server::received_type () } default: { - if (node->config.logging.network_packet_logging ()) - { - node->logger.try_log ("Unknown type received as block type"); - } + node->logger.debug (nano::log::type::bulk_push_server, "Unknown type received as block type"); break; } } @@ -282,11 +265,8 @@ void nano::bulk_push_server::received_block (boost::system::error_code const & e { if (node->network_params.work.validate_entry (*block)) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Insufficient work for bulk push block: %1%") % block->hash ().to_string ())); - } - node->stats.inc_detail_only (nano::stat::type::error, nano::stat::detail::insufficient_work); + node->logger.debug (nano::log::type::bulk_push_server, "Insufficient work for bulk push block: {}", block->hash ().to_string ()); + node->stats.inc (nano::stat::type::error, nano::stat::detail::insufficient_work); return; } node->process_active (std::move (block)); @@ -294,10 +274,7 @@ void nano::bulk_push_server::received_block (boost::system::error_code const & e } else { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Error deserializing block received from pull request"); - } + node->logger.debug (nano::log::type::bulk_push_server, "Error deserializing block received from pull request"); } } } diff --git a/nano/node/bootstrap/bootstrap_connections.cpp b/nano/node/bootstrap/bootstrap_connections.cpp index 6287add5a3..c843148d25 100644 --- a/nano/node/bootstrap/bootstrap_connections.cpp +++ b/nano/node/bootstrap/bootstrap_connections.cpp @@ -91,7 +91,8 @@ std::shared_ptr nano::bootstrap_connections::connection } if (result == nullptr && connections_count == 0 && new_connections_empty && attempt_a != nullptr) { - node.logger.try_log (boost::str (boost::format ("Bootstrap attempt stopped because there are no peers"))); + node.logger.debug (nano::log::type::bootstrap, "Bootstrap attempt stopped because there are no peers"); + lock.unlock (); attempt_a->stop (); } @@ -157,29 +158,24 @@ void nano::bootstrap_connections::connect_client (nano::tcp_endpoint const & end [this_l, socket, endpoint_a, push_front] (boost::system::error_code const & ec) { if (!ec) { - if (this_l->node.config.logging.bulk_pull_logging ()) - { - this_l->node.logger.try_log (boost::str (boost::format ("Connection established to %1%") % endpoint_a)); - } + this_l->node.logger.debug (nano::log::type::bootstrap, "Connection established to: {}", nano::util::to_str (endpoint_a)); + auto client (std::make_shared (this_l->node.shared (), std::make_shared (*this_l->node.shared (), socket), socket)); this_l->pool_connection (client, true, push_front); } else { - if (this_l->node.config.logging.network_logging ()) + switch (ec.value ()) { - switch (ec.value ()) - { - default: - this_l->node.logger.try_log (boost::str (boost::format ("Error initiating bootstrap connection to %1%: %2%") % endpoint_a % ec.message ())); - break; - case boost::system::errc::connection_refused: - case boost::system::errc::operation_canceled: - case boost::system::errc::timed_out: - case 995: // Windows The I/O operation has been aborted because of either a thread exit or an application request - case 10061: // Windows No connection could be made because the target machine actively refused it - break; - } + default: + this_l->node.logger.debug (nano::log::type::bootstrap, "Error initiating bootstrap connection to: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + break; + case boost::system::errc::connection_refused: + case boost::system::errc::operation_canceled: + case boost::system::errc::timed_out: + case 995: // Windows The I/O operation has been aborted because of either a thread exit or an application request + case 10061: // Windows No connection could be made because the target machine actively refused it + break; } } --this_l->connections_count; @@ -236,10 +232,12 @@ void nano::bootstrap_connections::populate_connections (bool repeat) // This is ~1.5kilobits/sec. if (elapsed_sec > nano::bootstrap_limits::bootstrap_minimum_termination_time_sec && blocks_per_sec < nano::bootstrap_limits::bootstrap_minimum_blocks_per_sec) { - if (node.config.logging.bulk_pull_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Stopping slow peer %1% (elapsed sec %2%s > %3%s and %4% blocks per second < %5%)") % client->channel->to_string () % elapsed_sec % nano::bootstrap_limits::bootstrap_minimum_termination_time_sec % blocks_per_sec % nano::bootstrap_limits::bootstrap_minimum_blocks_per_sec)); - } + node.logger.debug (nano::log::type::bootstrap, "Stopping slow peer {} (elapsed sec {} > {} and {} blocks per second < {})", + client->channel->to_string (), + elapsed_sec, + nano::bootstrap_limits::bootstrap_minimum_termination_time_sec, + blocks_per_sec, + nano::bootstrap_limits::bootstrap_minimum_blocks_per_sec); client->stop (true); new_clients.pop_back (); @@ -259,29 +257,27 @@ void nano::bootstrap_connections::populate_connections (bool repeat) // 4 -> 1, 8 -> 2, 16 -> 4, arbitrary, but seems to work well. auto drop = (int)roundf (sqrtf ((float)target - 2.0f)); - if (node.config.logging.bulk_pull_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Dropping %1% bulk pull peers, target connections %2%") % drop % target)); - } + node.logger.debug (nano::log::type::bootstrap, "Dropping {} bulk pull peers, target connections {}", drop, target); for (int i = 0; i < drop; i++) { auto client = sorted_connections.top (); - if (node.config.logging.bulk_pull_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Dropping peer with block rate %1%, block count %2% (%3%) ") % client->block_rate % client->block_count % client->channel->to_string ())); - } + node.logger.debug (nano::log::type::bootstrap, "Dropping peer with block rate {} and block count {} ({})", + client->block_rate.load (), + client->block_count.load (), + client->channel->to_string ()); client->stop (false); sorted_connections.pop (); } } - if (node.config.logging.bulk_pull_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Bulk pull connections: %1%, rate: %2% blocks/sec, bootstrap attempts %3%, remaining pulls: %4%") % connections_count.load () % (int)rate_sum % attempts_count % num_pulls)); - } + node.logger.debug (nano::log::type::bootstrap, "Bulk pull connections: {}, rate: {} blocks/sec, bootstrap attempts {}, remaining pulls: {}", + connections_count.load (), + (int)rate_sum, + attempts_count, + num_pulls); if (connections_count < target && (attempts_count != 0 || new_connections_empty) && !stopped) { @@ -423,11 +419,13 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a, } else { - if (node.config.logging.bulk_pull_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Failed to pull account %1% or head block %2% down to %3% after %4% attempts and %5% blocks processed") % pull.account_or_head.to_account () % pull.account_or_head.to_string () % pull.end.to_string () % pull.attempts % pull.processed)); - } node.stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in); + node.logger.debug (nano::log::type::bootstrap, "Failed to pull account {} or head block {} down to {} after {} attempts and {} blocks processed", + pull.account_or_head.to_account (), + pull.account_or_head.to_string (), + pull.end.to_string (), + pull.attempts, + pull.processed); if (lazy && pull.processed > 0) { @@ -445,18 +443,10 @@ void nano::bootstrap_connections::clear_pulls (uint64_t bootstrap_id_a) { { nano::lock_guard lock{ mutex }; - auto i (pulls.begin ()); - while (i != pulls.end ()) - { - if (i->bootstrap_id == bootstrap_id_a) - { - i = pulls.erase (i); - } - else - { - ++i; - } - } + + erase_if (pulls, [bootstrap_id_a] (auto const & pull) { + return pull.bootstrap_id == bootstrap_id_a; + }); } condition.notify_all (); } diff --git a/nano/node/bootstrap/bootstrap_frontier.cpp b/nano/node/bootstrap/bootstrap_frontier.cpp index 6b8766fc24..6380bd61a9 100644 --- a/nano/node/bootstrap/bootstrap_frontier.cpp +++ b/nano/node/bootstrap/bootstrap_frontier.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -42,10 +43,7 @@ void nano::frontier_req_client::run (nano::account const & start_account_a, uint } else { - if (node->config.logging.network_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error while sending bootstrap request %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::frontier_req_client, "Error while sending bootstrap request: {}", ec.message ()); } }, nano::transport::buffer_drop_policy::no_limiter_drop); @@ -76,10 +74,7 @@ void nano::frontier_req_client::receive_frontier () } else { - if (node->config.logging.network_message_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Invalid size: expected %1%, got %2%") % nano::frontier_req_client::size_frontier % size_a)); - } + node->logger.debug (nano::log::type::frontier_req_client, "Invalid size: expected {}, got {}", nano::frontier_req_client::size_frontier, size_a); } }); } @@ -137,14 +132,17 @@ void nano::frontier_req_client::received_frontier (boost::system::error_code con double age_factor = (frontiers_age == std::numeric_limits::max ()) ? 1.0 : 1.5; // Allow slower frontiers receive for requests with age if (elapsed_sec > nano::bootstrap_limits::bootstrap_connection_warmup_time_sec && blocks_per_sec * age_factor < nano::bootstrap_limits::bootstrap_minimum_frontier_blocks_per_sec) { - node->logger.try_log (boost::str (boost::format ("Aborting frontier req because it was too slow: %1% frontiers per second, last %2%") % blocks_per_sec % account.to_account ())); + node->logger.debug (nano::log::type::frontier_req_client, "Aborting frontier req because it was too slow: {} frontiers per second, last {}", blocks_per_sec, account.to_account ()); + promise.set_value (true); return; } + if (attempt->should_log ()) { - node->logger.always_log (boost::str (boost::format ("Received %1% frontiers from %2%") % std::to_string (count) % connection->channel->to_string ())); + node->logger.debug (nano::log::type::frontier_req_client, "Received {} frontiers from {}", count, connection->channel->to_string ()); } + if (!account.is_zero () && count <= count_limit) { last_account = account; @@ -203,10 +201,8 @@ void nano::frontier_req_client::received_frontier (boost::system::error_code con } // Prevent new frontier_req requests attempt->set_start_account (std::numeric_limits::max ()); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Bulk push cost: ", bulk_push_cost); - } + + node->logger.debug (nano::log::type::frontier_req_client, "Bulk push cost: {}", bulk_push_cost); } else { @@ -225,10 +221,7 @@ void nano::frontier_req_client::received_frontier (boost::system::error_code con } else { - if (node->config.logging.network_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error while receiving frontier %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::frontier_req_client, "Error while receiving frontier: {}", ec.message ()); } } @@ -283,6 +276,11 @@ void nano::frontier_req_server::send_next () } if (!current.is_zero () && count < request->count) { + node->logger.trace (nano::log::type::frontier_req_server, nano::log::detail::sending_frontier, + nano::log::arg{ "account", current.to_account () }, // TODO: Convert to lazy eval + nano::log::arg{ "frontier", frontier }, + nano::log::arg{ "socket", connection->socket }); + std::vector send_buffer; { nano::vectorstream stream (send_buffer); @@ -291,11 +289,8 @@ void nano::frontier_req_server::send_next () debug_assert (!current.is_zero ()); debug_assert (!frontier.is_zero ()); } + auto this_l (shared_from_this ()); - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Sending frontier for %1% %2%") % current.to_account () % frontier.to_string ())); - } next (); connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l] (boost::system::error_code const & ec, std::size_t size_a) { this_l->sent_action (ec, size_a); @@ -321,11 +316,10 @@ void nano::frontier_req_server::send_finished () write (stream, zero.bytes); write (stream, zero.bytes); } + + node->logger.debug (nano::log::type::frontier_req_server, "Frontier sending finished"); + auto this_l (shared_from_this ()); - if (node->config.logging.network_logging ()) - { - node->logger.try_log ("Frontier sending finished"); - } connection->socket->async_write (nano::shared_const_buffer (std::move (send_buffer)), [this_l] (boost::system::error_code const & ec, std::size_t size_a) { this_l->no_block_sent (ec, size_a); }); @@ -344,10 +338,7 @@ void nano::frontier_req_server::no_block_sent (boost::system::error_code const & } else { - if (node->config.logging.network_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error sending frontier finish: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::frontier_req_server, "Error sending frontier finish: {}", ec.message ()); } } @@ -368,10 +359,7 @@ void nano::frontier_req_server::sent_action (boost::system::error_code const & e } else { - if (node->config.logging.network_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error sending frontier pair: %1%") % ec.message ())); - } + node->logger.debug (nano::log::type::frontier_req_server, "Error sending frontier pair: {}", ec.message ()); } } diff --git a/nano/node/bootstrap/bootstrap_frontier.hpp b/nano/node/bootstrap/bootstrap_frontier.hpp index 1f6575cd0f..75ee9c1ab9 100644 --- a/nano/node/bootstrap/bootstrap_frontier.hpp +++ b/nano/node/bootstrap/bootstrap_frontier.hpp @@ -1,7 +1,10 @@ #pragma once +#include + #include #include +#include namespace nano { diff --git a/nano/node/bootstrap/bootstrap_lazy.cpp b/nano/node/bootstrap/bootstrap_lazy.cpp index 28e5cf6ad0..4646cbaa68 100644 --- a/nano/node/bootstrap/bootstrap_lazy.cpp +++ b/nano/node/bootstrap/bootstrap_lazy.cpp @@ -1,7 +1,9 @@ +#include #include #include #include #include +#include #include @@ -250,11 +252,11 @@ void nano::bootstrap_attempt_lazy::run () } if (!stopped) { - node->logger.try_log ("Completed lazy pulls"); + node->logger.debug (nano::log::type::bootstrap_lazy, "Completed lazy pulls"); } if (lazy_has_expired ()) { - node->logger.try_log (boost::str (boost::format ("Lazy bootstrap attempt ID %1% expired") % id)); + node->logger.debug (nano::log::type::bootstrap_lazy, "Lazy bootstrap attempt ID {} expired", id); } lock.unlock (); stop (); @@ -290,9 +292,9 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptrsource ().is_zero () && !node->ledger.block_or_pruned_exists (block_a->source ()) && block_a->source () != node->network_params.ledger.genesis->account ()) + if (block_a->source_field () && !node->ledger.block_or_pruned_exists (block_a->source_field ().value ()) && block_a->source_field ().value () != node->network_params.ledger.genesis->account ()) { - lazy_add (block_a->source (), retry_limit); + lazy_add (block_a->source_field ().value (), retry_limit); } else if (block_a->type () == nano::block_type::state) { @@ -302,7 +304,7 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptrtype () == nano::block_type::state || block_a->type () == nano::block_type::send)) { - lazy_balances.emplace (hash, block_a->balance ().number ()); + lazy_balances.emplace (hash, block_a->balance_field ().value ().number ()); } // Clearing lazy balances for previous block if (!block_a->previous ().is_zero () && lazy_balances.find (block_a->previous ()) != lazy_balances.end ()) @@ -311,7 +313,7 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptrblock_processor.add (block_a); + node->block_processor.add (block_a, nano::block_source::bootstrap_legacy); } // Force drop lazy bootstrap connection for long bulk_pull if (pull_blocks_processed > max_blocks) @@ -346,11 +348,10 @@ void nano::bootstrap_attempt_lazy::lazy_block_state (std::shared_ptrledger.block_or_pruned_exists (transaction, previous)) { - bool error_or_pruned (false); - auto previous_balance (node->ledger.balance_safe (transaction, previous, error_or_pruned)); - if (!error_or_pruned) + auto previous_balance = node->ledger.balance (transaction, previous); + if (previous_balance) { - if (previous_balance <= balance) + if (previous_balance.value () <= balance) { lazy_add (link, retry_limit); } @@ -394,7 +395,7 @@ void nano::bootstrap_attempt_lazy::lazy_block_state_backlog_check (std::shared_p // Retrieve balance for previous state & send blocks if (block_a->type () == nano::block_type::state || block_a->type () == nano::block_type::send) { - if (block_a->balance ().number () <= next_block.balance) // balance + if (block_a->balance_field ().value ().number () <= next_block.balance) // balance { lazy_add (next_block.link, next_block.retry_limit); // link } @@ -423,11 +424,10 @@ void nano::bootstrap_attempt_lazy::lazy_backlog_cleanup () if (node->ledger.block_or_pruned_exists (transaction, it->first)) { auto next_block (it->second); - bool error_or_pruned (false); - auto balance (node->ledger.balance_safe (transaction, it->first, error_or_pruned)); - if (!error_or_pruned) + auto balance = node->ledger.balance (transaction, it->first); + if (balance) { - if (balance <= next_block.balance) // balance + if (balance.value () <= next_block.balance) // balance { lazy_add (next_block.link, next_block.retry_limit); // link } @@ -613,7 +613,7 @@ void nano::bootstrap_attempt_wallet::run () } if (!stopped) { - node->logger.try_log ("Completed wallet lazy pulls"); + node->logger.info (nano::log::type::bootstrap_lazy, "Completed wallet lazy pulls"); } lock.unlock (); stop (); diff --git a/nano/node/bootstrap/bootstrap_legacy.cpp b/nano/node/bootstrap/bootstrap_legacy.cpp index 481d6df85b..9badee97cc 100644 --- a/nano/node/bootstrap/bootstrap_legacy.cpp +++ b/nano/node/bootstrap/bootstrap_legacy.cpp @@ -88,14 +88,6 @@ void nano::bootstrap_attempt_legacy::request_push (nano::unique_lockconfig.logging.network_logging ()) - { - node->logger.try_log ("Exiting bulk push client"); - if (error) - { - node->logger.try_log ("Bulk push client failed"); - } - } } void nano::bootstrap_attempt_legacy::add_frontier (nano::pull_info const & pull_a) @@ -186,16 +178,13 @@ bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lockconfig.logging.network_logging ()) + if (!result) { - if (!result) - { - node->logger.try_log (boost::str (boost::format ("Completed frontier request, %1% out of sync accounts according to %2%") % account_count % connection_l->channel->to_string ())); - } - else - { - node->stats.inc (nano::stat::type::error, nano::stat::detail::frontier_req, nano::stat::dir::out); - } + node->logger.debug (nano::log::type::bootstrap_legacy, "Completed frontier request, {} out of sync accounts according to {}", account_count.load (), connection_l->channel->to_string ()); + } + else + { + node->stats.inc (nano::stat::type::error, nano::stat::detail::frontier_req, nano::stat::dir::out); } } return result; @@ -233,33 +222,30 @@ void nano::bootstrap_attempt_legacy::run () // clang-format off condition.wait (lock, [&stopped = stopped, &pulling = pulling] { return stopped || pulling == 0; }); } - // Flushing may resolve forks which can add more pulls - node->logger.try_log ("Flushing unchecked blocks"); - lock.unlock (); - node->block_processor.flush (); - lock.lock (); + + // TODO: This check / wait is a heuristic and should be improved. + auto wait_start = std::chrono::steady_clock::now (); + while (!stopped && node->block_processor.size () != 0 && ((std::chrono::steady_clock::now () - wait_start) < std::chrono::seconds{ 10 })) + { + condition.wait_for (lock, std::chrono::milliseconds{ 100 }, [this, node] { return stopped || node->block_processor.size () == 0; }); + } + if (start_account.number () != std::numeric_limits::max ()) { - node->logger.try_log (boost::str (boost::format ("Finished flushing unchecked blocks, requesting new frontiers after %1%") % start_account.to_account ())); + node->logger.debug(nano::log::type::bootstrap_legacy, "Requesting new frontiers after: {}", start_account.to_account ()); + // Requesting new frontiers run_start (lock); } - else - { - node->logger.try_log ("Finished flushing unchecked blocks"); - } } if (!stopped) { - node->logger.try_log ("Completed legacy pulls"); + node->logger.debug(nano::log::type::bootstrap_legacy, "Completed legacy pulls"); + if (!node->flags.disable_bootstrap_bulk_push_client) { request_push (lock); } - if (!stopped) - { - node->unchecked_cleanup (); - } } lock.unlock (); stop (); diff --git a/nano/node/bootstrap/bootstrap_server.cpp b/nano/node/bootstrap/bootstrap_server.cpp index 8fda11587c..3128b9ad20 100644 --- a/nano/node/bootstrap/bootstrap_server.cpp +++ b/nano/node/bootstrap/bootstrap_server.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -192,7 +193,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (store::transaction const & t { case asc_pull_req::hash_type::block: { - if (store.block.exists (transaction, request.start.as_block_hash ())) + if (ledger.block_exists (transaction, request.start.as_block_hash ())) { return prepare_response (transaction, id, request.start.as_block_hash (), count); } @@ -253,13 +254,13 @@ std::vector> nano::bootstrap_server::prepare_blocks std::vector> result; if (!start_block.is_zero ()) { - std::shared_ptr current = store.block.get (transaction, start_block); + std::shared_ptr current = ledger.block (transaction, start_block); while (current && result.size () < count) { result.push_back (current); auto successor = current->sideband ().successor; - current = store.block.get (transaction, successor); + current = ledger.block (transaction, successor); } } return result; @@ -286,7 +287,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (const store::transaction & t case asc_pull_req::hash_type::block: { // Try to lookup account assuming target is block hash - target = ledger.account_safe (transaction, request.target.as_block_hash ()); + target = ledger.account (transaction, request.target.as_block_hash ()).value_or (0); } break; } @@ -337,4 +338,4 @@ nano::asc_pull_ack nano::bootstrap_server::process (const store::transaction & t response.payload = response_payload; response.update_header (); return response; -} \ No newline at end of file +} diff --git a/nano/node/bootstrap_ascending/peer_scoring.cpp b/nano/node/bootstrap_ascending/peer_scoring.cpp index faeb4fe306..e9b1059662 100644 --- a/nano/node/bootstrap_ascending/peer_scoring.cpp +++ b/nano/node/bootstrap_ascending/peer_scoring.cpp @@ -82,18 +82,18 @@ std::size_t nano::bootstrap_ascending::peer_scoring::size () const void nano::bootstrap_ascending::peer_scoring::timeout () { auto & index = scoring.get (); - for (auto score = index.begin (), n = index.end (); score != n;) - { - if (auto channel = score->shared ()) + + erase_if (index, [] (auto const & score) { + if (auto channel = score.shared ()) { if (channel->alive ()) { - ++score; - continue; + return false; // Keep } } - score = index.erase (score); - } + return true; + }); + for (auto score = scoring.begin (), n = scoring.end (); score != n; ++score) { scoring.modify (score, [] (auto & score_a) { diff --git a/nano/node/bootstrap_ascending/service.cpp b/nano/node/bootstrap_ascending/service.cpp index 76e2aac31a..e75a26c247 100644 --- a/nano/node/bootstrap_ascending/service.cpp +++ b/nano/node/bootstrap_ascending/service.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -34,11 +35,10 @@ nano::bootstrap_ascending::service::service (nano::node_config & config_a, nano: nano::lock_guard lock{ mutex }; auto transaction = ledger.store.tx_begin_read (); - for (auto const & [result, block] : batch) + for (auto const & [result, context] : batch) { - debug_assert (block != nullptr); - - inspect (transaction, result, *block); + debug_assert (context.block != nullptr); + inspect (transaction, result, *context.block); } } @@ -125,50 +125,33 @@ std::size_t nano::bootstrap_ascending::service::score_size () const - Marks an account as blocked if the result code is gap source as there is no reason request additional blocks for this account until the dependency is resolved - Marks an account as forwarded if it has been recently referenced by a block that has been inserted. */ -void nano::bootstrap_ascending::service::inspect (store::transaction const & tx, nano::process_return const & result, nano::block const & block) +void nano::bootstrap_ascending::service::inspect (store::transaction const & tx, nano::block_status const & result, nano::block const & block) { auto const hash = block.hash (); - switch (result.code) + switch (result) { - case nano::process_result::progress: + case nano::block_status::progress: { - const auto account = ledger.account (tx, hash); - const auto is_send = ledger.is_send (tx, block); + const auto account = block.account (); // If we've inserted any block in to an account, unmark it as blocked accounts.unblock (account); accounts.priority_up (account); accounts.timestamp (account, /* reset timestamp */ true); - if (is_send) + if (block.is_send ()) { - // TODO: Encapsulate this as a helper somewhere - nano::account destination{ 0 }; - switch (block.type ()) - { - case nano::block_type::send: - destination = block.destination (); - break; - case nano::block_type::state: - destination = block.link ().as_account (); - break; - default: - debug_assert (false, "unexpected block type"); - break; - } - if (!destination.is_zero ()) - { - accounts.unblock (destination, hash); // Unblocking automatically inserts account into priority set - accounts.priority_up (destination); - } + auto destination = block.destination (); + accounts.unblock (destination, hash); // Unblocking automatically inserts account into priority set + accounts.priority_up (destination); } } break; - case nano::process_result::gap_source: + case nano::block_status::gap_source: { - const auto account = block.previous ().is_zero () ? block.account () : ledger.account (tx, block.previous ()); - const auto source = block.source ().is_zero () ? block.link ().as_block_hash () : block.source (); + const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.account (tx, block.previous ()).value (); + const auto source = block.source_field ().value_or (block.link_field ().value_or (0).as_block_hash ()); // Mark account as blocked because it is missing the source block accounts.block (account, source); @@ -176,12 +159,12 @@ void nano::bootstrap_ascending::service::inspect (store::transaction const & tx, // TODO: Track stats } break; - case nano::process_result::old: + case nano::block_status::old: { // TODO: Track stats } break; - case nano::process_result::gap_previous: + case nano::block_status::gap_previous: { // TODO: Track stats } @@ -388,7 +371,7 @@ void nano::bootstrap_ascending::service::process (const nano::asc_pull_ack::bloc for (auto & block : response.blocks) { - block_processor.add (block); + block_processor.add (block, nano::block_source::bootstrap); } nano::lock_guard lock{ mutex }; throttle.add (true); @@ -456,7 +439,7 @@ nano::bootstrap_ascending::service::verify_result nano::bootstrap_ascending::ser case async_tag::query_type::blocks_by_account: { // Open & state blocks always contain account field - if (first->account () != tag.start.as_account ()) + if (first->account_field () != tag.start.as_account ()) { // TODO: Stat & log return verify_result::invalid; diff --git a/nano/node/bootstrap_ascending/service.hpp b/nano/node/bootstrap_ascending/service.hpp index 3c7a436f7c..4b7ed0e1ed 100644 --- a/nano/node/bootstrap_ascending/service.hpp +++ b/nano/node/bootstrap_ascending/service.hpp @@ -88,7 +88,7 @@ namespace bootstrap_ascending private: /* Inspects a block that has been processed by the block processor */ - void inspect (store::transaction const &, nano::process_return const & result, nano::block const & block); + void inspect (store::transaction const &, nano::block_status const & result, nano::block const & block); void throttle_if_needed (nano::unique_lock & lock); void run (); diff --git a/nano/node/cli.cpp b/nano/node/cli.cpp index 721edd67ff..449bb755a7 100644 --- a/nano/node/cli.cpp +++ b/nano/node/cli.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,7 @@ #include #include #include +#include #include @@ -58,7 +60,7 @@ void nano::add_node_options (boost::program_options::options_description & descr ("rebuild_database", "Rebuild LMDB database with vacuum for best compaction") ("migrate_database_lmdb_to_rocksdb", "Migrates LMDB database to RocksDB") ("diagnostics", "Run internal diagnostics") - ("generate_config", boost::program_options::value (), "Write configuration to stdout, populated with defaults suitable for this system. Pass the configuration type node, rpc or tls. See also use_defaults.") + ("generate_config", boost::program_options::value (), "Write configuration to stdout, populated with defaults suitable for this system. Pass the configuration type node, rpc or log. See also use_defaults.") ("key_create", "Generates a adhoc random keypair and prints it to stdout") ("key_expand", "Derive public key and account number from ") ("wallet_add_adhoc", "Insert in to ") @@ -131,8 +133,6 @@ std::error_code nano::update_flags (nano::node_flags & flags_a, boost::program_o flags_a.disable_bootstrap_listener = (vm.count ("disable_bootstrap_listener") > 0); } flags_a.disable_providing_telemetry_metrics = (vm.count ("disable_providing_telemetry_metrics") > 0); - flags_a.disable_unchecked_cleanup = (vm.count ("disable_unchecked_cleanup") > 0); - flags_a.disable_unchecked_drop = (vm.count ("disable_unchecked_drop") > 0); flags_a.disable_block_processor_unchecked_deletion = (vm.count ("disable_block_processor_unchecked_deletion") > 0); flags_a.enable_pruning = (vm.count ("enable_pruning") > 0); flags_a.allow_bootstrap_peers_duplicates = (vm.count ("allow_bootstrap_peers_duplicates") > 0); @@ -254,6 +254,9 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map if (vm.count ("initialize")) { + // TODO: --config flag overrides are not taken into account here + nano::logger::initialize (nano::log_config::daemon_default (), data_path); + auto node_flags = nano::inactive_node_flag_defaults (); node_flags.read_only = false; nano::update_flags (node_flags, vm); @@ -671,6 +674,12 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map nano::rpc_config config{ nano::dev::network_params.network }; config.serialize_toml (toml); } + else if (type == "log") + { + valid_type = true; + nano::log_config config = nano::log_config::sample_config (); + config.serialize_toml (toml); + } else if (type == "tls") { valid_type = true; @@ -730,7 +739,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map environment.dump (std::cout); std::stringstream stream; environment.dump (stream); - inactive_node->node->logger.always_log (stream.str ()); + std::cout << stream.str () << std::endl; } else { diff --git a/nano/node/confirmation_height_bounded.cpp b/nano/node/confirmation_height_bounded.cpp index a2301f891d..dfb7dea6d7 100644 --- a/nano/node/confirmation_height_bounded.cpp +++ b/nano/node/confirmation_height_bounded.cpp @@ -1,7 +1,6 @@ -#include +#include #include #include -#include #include #include #include @@ -12,11 +11,10 @@ #include -nano::confirmation_height_bounded::confirmation_height_bounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logging const & logging_a, nano::logger_mt & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : +nano::confirmation_height_bounded::confirmation_height_bounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : ledger (ledger_a), write_database_queue (write_database_queue_a), batch_separate_pending_min_time (batch_separate_pending_min_time_a), - logging (logging_a), logger (logger_a), stopped (stopped_a), batch_write_size (batch_write_size_a), @@ -86,7 +84,7 @@ void nano::confirmation_height_bounded::process (std::shared_ptr or } else { - block = ledger.store.block.get (transaction, current); + block = ledger.block (transaction, current); } if (!block) @@ -101,17 +99,12 @@ void nano::confirmation_height_bounded::process (std::shared_ptr or } else { - auto error_str = (boost::format ("Ledger mismatch trying to set confirmation height for block %1% (bounded processor)") % current.to_string ()).str (); - logger.always_log (error_str); - std::cerr << error_str << std::endl; + logger.critical (nano::log::type::conf_processor_bounded, "Ledger mismatch trying to set confirmation height for block {} (bounded processor)", current.to_string ()); + release_assert (block); } } - nano::account account (block->account ()); - if (account.is_zero ()) - { - account = block->sideband ().account; - } + auto account = block->account (); // Checks if we have encountered this account before but not commited changes yet, if so then update the cached confirmation height nano::confirmation_height_info confirmation_height_info; @@ -231,7 +224,7 @@ nano::block_hash nano::confirmation_height_bounded::get_least_unconfirmed_hash_f { if (block_height_a > confirmation_height_info_a.height) { - auto block (ledger.store.block.get (transaction_a, confirmation_height_info_a.frontier)); + auto block = ledger.block (transaction_a, confirmation_height_info_a.frontier); release_assert (block != nullptr); least_unconfirmed_hash = block->sideband ().successor; block_height_a = block->sideband ().height + 1; @@ -259,20 +252,14 @@ bool nano::confirmation_height_bounded::iterate (store::read_transaction const & // Keep iterating upwards until we either reach the desired block or the second receive. // Once a receive is cemented, we can cement all blocks above it until the next receive, so store those details for later. ++num_blocks; - auto block = ledger.store.block.get (transaction_a, hash); - auto source (block->source ()); - if (source.is_zero ()) - { - source = block->link ().as_block_hash (); - } - - if (!source.is_zero () && !ledger.is_epoch_link (source) && ledger.store.block.exists (transaction_a, source)) + auto block = ledger.block (transaction_a, hash); + if (block->is_receive () && ledger.block_exists (transaction_a, block->source ())) { hit_receive = true; reached_target = true; auto const & sideband (block->sideband ()); auto next = !sideband.successor.is_zero () && sideband.successor != top_level_hash_a ? boost::optional (sideband.successor) : boost::none; - receive_source_pairs_a.push_back ({ receive_chain_details{ account_a, sideband.height, hash, top_level_hash_a, next, bottom_height_a, bottom_hash_a }, source }); + receive_source_pairs_a.push_back ({ receive_chain_details{ account_a, sideband.height, hash, top_level_hash_a, next, bottom_height_a, bottom_hash_a }, block->source () }); // Store a checkpoint every max_items so that we can always traverse a long number of accounts to genesis if (receive_source_pairs_a.size () % max_items == 0) { @@ -388,7 +375,7 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope // Extra debug checks nano::confirmation_height_info confirmation_height_info; ledger.store.confirmation_height.get (transaction, account, confirmation_height_info); - auto block (ledger.store.block.get (transaction, confirmed_frontier)); + auto block = ledger.block (transaction, confirmed_frontier); debug_assert (block != nullptr); debug_assert (block->sideband ().height == confirmation_height_info.height + num_blocks_cemented); #endif @@ -418,14 +405,14 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope } else { - auto block = ledger.store.block.get (transaction, confirmation_height_info.frontier); + auto block = ledger.block (transaction, confirmation_height_info.frontier); new_cemented_frontier = block->sideband ().successor; num_blocks_confirmed = pending.top_height - confirmation_height_info.height; start_height = confirmation_height_info.height + 1; } auto total_blocks_cemented = 0; - auto block = ledger.store.block.get (transaction, new_cemented_frontier); + auto block = ledger.block (transaction, new_cemented_frontier); // Cementing starts from the bottom of the chain and works upwards. This is because chains can have effectively // an infinite number of send/change blocks in a row. We don't want to hold the write transaction open for too long. @@ -433,9 +420,8 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope { if (!block) { - auto error_str = (boost::format ("Failed to write confirmation height for block %1% (bounded processor)") % new_cemented_frontier.to_string ()).str (); - logger.always_log (error_str); - std::cerr << error_str << std::endl; + logger.critical (nano::log::type::conf_processor_bounded, "Failed to write confirmation height for block {} (bounded processor)", new_cemented_frontier.to_string ()); + // Undo any blocks about to be cemented from this account for this pending write. cemented_blocks.erase (cemented_blocks.end () - num_blocks_iterated, cemented_blocks.end ()); error = true; @@ -455,10 +441,6 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope total_blocks_cemented += num_blocks_cemented; write_confirmation_height (num_blocks_cemented, start_height + total_blocks_cemented - 1, new_cemented_frontier); transaction.commit (); - if (logging.timing_logging ()) - { - logger.always_log (boost::str (boost::format ("Cemented %1% blocks in %2% %3% (bounded processor)") % cemented_blocks.size () % time_spent_cementing % cemented_batch_timer.unit ())); - } // Update the maximum amount of blocks to write next time based on the time it took to cement this batch. if (time_spent_cementing > maximum_batch_write_time) @@ -489,7 +471,7 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope if (!last_iteration) { new_cemented_frontier = block->sideband ().successor; - block = ledger.store.block.get (transaction, new_cemented_frontier); + block = ledger.block (transaction, new_cemented_frontier); } else { @@ -521,11 +503,8 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope --pending_writes_size; } } - auto time_spent_cementing = cemented_batch_timer.since_start ().count (); - if (logging.timing_logging () && time_spent_cementing > 50) - { - logger.always_log (boost::str (boost::format ("Cemented %1% blocks in %2% %3% (bounded processor)") % cemented_blocks.size () % time_spent_cementing % cemented_batch_timer.unit ())); - } + + auto time_spent_cementing = cemented_batch_timer.since_start (); // Scope guard could have been released earlier (0 cemented_blocks would indicate that) if (scoped_write_guard_a.is_owned () && !cemented_blocks.empty ()) @@ -537,7 +516,8 @@ void nano::confirmation_height_bounded::cement_blocks (nano::write_guard & scope // Bail if there was an error. This indicates that there was a fatal issue with the ledger // (the blocks probably got rolled back when they shouldn't have). release_assert (!error); - if (time_spent_cementing > maximum_batch_write_time) + + if (time_spent_cementing.count () > maximum_batch_write_time) { // Reduce (unless we have hit a floor) batch_write_size = std::max (minimum_batch_write_size, batch_write_size - amount_to_change); diff --git a/nano/node/confirmation_height_bounded.hpp b/nano/node/confirmation_height_bounded.hpp index c176b41686..a5052b1452 100644 --- a/nano/node/confirmation_height_bounded.hpp +++ b/nano/node/confirmation_height_bounded.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -11,15 +12,14 @@ namespace nano { class ledger; -class logging; -class logger_mt; class write_database_queue; class write_guard; class confirmation_height_bounded final { public: - confirmation_height_bounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logging const &, nano::logger_mt &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); + confirmation_height_bounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logger &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); + bool pending_empty () const; void clear_process_vars (); void process (std::shared_ptr original_block); @@ -121,8 +121,7 @@ class confirmation_height_bounded final nano::ledger & ledger; nano::write_database_queue & write_database_queue; std::chrono::milliseconds batch_separate_pending_min_time; - nano::logging const & logging; - nano::logger_mt & logger; + nano::logger & logger; std::atomic & stopped; uint64_t & batch_write_size; std::function> const &)> notify_observers_callback; diff --git a/nano/node/confirmation_height_processor.cpp b/nano/node/confirmation_height_processor.cpp index 6cf9772999..e60816444a 100644 --- a/nano/node/confirmation_height_processor.cpp +++ b/nano/node/confirmation_height_processor.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -9,16 +9,16 @@ #include -nano::confirmation_height_processor::confirmation_height_processor (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logging const & logging_a, nano::logger_mt & logger_a, boost::latch & latch, confirmation_height_mode mode_a) : +nano::confirmation_height_processor::confirmation_height_processor (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, boost::latch & latch, confirmation_height_mode mode_a) : ledger (ledger_a), write_database_queue (write_database_queue_a), unbounded_processor ( - ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logging_a, logger_a, stopped, batch_write_size, + ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logger_a, stopped, batch_write_size, /* cemented_callback */ [this] (auto & cemented_blocks) { this->notify_cemented (cemented_blocks); }, /* already cemented_callback */ [this] (auto const & block_hash_a) { this->notify_already_cemented (block_hash_a); }, /* awaiting_processing_size_query */ [this] () { return this->awaiting_processing_size (); }), bounded_processor ( - ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logging_a, logger_a, stopped, batch_write_size, + ledger_a, write_database_queue_a, batch_separate_pending_min_time_a, logger_a, stopped, batch_write_size, /* cemented_callback */ [this] (auto & cemented_blocks) { this->notify_cemented (cemented_blocks); }, /* already cemented_callback */ [this] (auto const & block_hash_a) { this->notify_already_cemented (block_hash_a); }, /* awaiting_processing_size_query */ [this] () { return this->awaiting_processing_size (); }), @@ -240,3 +240,8 @@ nano::block_hash nano::confirmation_height_processor::current () const nano::lock_guard lk (mutex); return original_block ? original_block->hash () : 0; } + +std::reference_wrapper nano::confirmation_height_processor::block_wrapper::hash () const +{ + return block->hash (); +} diff --git a/nano/node/confirmation_height_processor.hpp b/nano/node/confirmation_height_processor.hpp index 88f2d1a15b..828a616111 100644 --- a/nano/node/confirmation_height_processor.hpp +++ b/nano/node/confirmation_height_processor.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -24,14 +25,14 @@ class latch; namespace nano { class ledger; -class logger_mt; class write_database_queue; class confirmation_height_processor final { public: - confirmation_height_processor (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logging const &, nano::logger_mt &, boost::latch & initialized_latch, confirmation_height_mode = confirmation_height_mode::automatic); + confirmation_height_processor (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger &, boost::latch & initialized_latch, confirmation_height_mode = confirmation_height_mode::automatic); ~confirmation_height_processor (); + void pause (); void unpause (); void stop (); @@ -64,10 +65,7 @@ class confirmation_height_processor final { } - std::reference_wrapper hash () const - { - return block->hash (); - } + std::reference_wrapper hash () const; std::shared_ptr block; }; diff --git a/nano/node/confirmation_height_unbounded.cpp b/nano/node/confirmation_height_unbounded.cpp index 9a458b9c8c..20e7101c13 100644 --- a/nano/node/confirmation_height_unbounded.cpp +++ b/nano/node/confirmation_height_unbounded.cpp @@ -1,7 +1,6 @@ -#include +#include #include #include -#include #include #include #include @@ -12,11 +11,10 @@ #include -nano::confirmation_height_unbounded::confirmation_height_unbounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logging const & logging_a, nano::logger_mt & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : +nano::confirmation_height_unbounded::confirmation_height_unbounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger & logger_a, std::atomic & stopped_a, uint64_t & batch_write_size_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : ledger (ledger_a), write_database_queue (write_database_queue_a), batch_separate_pending_min_time (batch_separate_pending_min_time_a), - logging (logging_a), logger (logger_a), stopped (stopped_a), batch_write_size (batch_write_size_a), @@ -77,17 +75,11 @@ void nano::confirmation_height_unbounded::process (std::shared_ptr } if (!block) { - auto error_str = (boost::format ("Ledger mismatch trying to set confirmation height for block %1% (unbounded processor)") % current.to_string ()).str (); - logger.always_log (error_str); - std::cerr << error_str << std::endl; + logger.critical (nano::log::type::conf_processor_unbounded, "Ledger mismatch trying to set confirmation height for block {} (unbounded processor)", current.to_string ()); } release_assert (block); - nano::account account (block->account ()); - if (account.is_zero ()) - { - account = block->sideband ().account; - } + auto account = block->account (); auto block_height = block->sideband ().height; uint64_t confirmation_height = 0; @@ -220,13 +212,7 @@ void nano::confirmation_height_unbounded::collect_unconfirmed_receive_and_source if (block) { - auto source (block->source ()); - if (source.is_zero ()) - { - source = block->link ().as_block_hash (); - } - - if (!source.is_zero () && !ledger.is_epoch_link (source) && ledger.store.block.exists (transaction_a, source)) + if (block->is_receive () && ledger.block_exists (transaction_a, block->source ())) { if (!hit_receive && !block_callback_data_a.empty ()) { @@ -241,7 +227,7 @@ void nano::confirmation_height_unbounded::collect_unconfirmed_receive_and_source hit_receive = true; auto block_height = confirmation_height_a + num_to_confirm; - receive_source_pairs_a.emplace_back (std::make_shared (account_a, hash, block_height, 1, std::vector{ hash }), source); + receive_source_pairs_a.emplace_back (std::make_shared (account_a, hash, block_height, 1, std::vector{ hash }), block->source ()); } else if (is_original_block) { @@ -381,7 +367,7 @@ void nano::confirmation_height_unbounded::cement_blocks (nano::write_guard & sco auto confirmation_height = confirmation_height_info.height; if (pending.height > confirmation_height) { - auto block = ledger.store.block.get (transaction, pending.hash); + auto block = ledger.block (transaction, pending.hash); debug_assert (ledger.pruning || block != nullptr); debug_assert (ledger.pruning || block->sideband ().height == pending.height); @@ -395,9 +381,8 @@ void nano::confirmation_height_unbounded::cement_blocks (nano::write_guard & sco } else { - auto error_str = (boost::format ("Failed to write confirmation height for block %1% (unbounded processor)") % pending.hash.to_string ()).str (); - logger.always_log (error_str); - std::cerr << error_str << std::endl; + logger.critical (nano::log::type::conf_processor_unbounded, "Failed to write confirmation height for block {} (unbounded processor)", pending.hash.to_string ()); + error = true; break; } @@ -424,10 +409,6 @@ void nano::confirmation_height_unbounded::cement_blocks (nano::write_guard & sco } auto time_spent_cementing = cemented_batch_timer.since_start ().count (); - if (logging.timing_logging () && time_spent_cementing > 50) - { - logger.always_log (boost::str (boost::format ("Cemented %1% blocks in %2% %3% (unbounded processor)") % cemented_blocks.size () % time_spent_cementing % cemented_batch_timer.unit ())); - } scoped_write_guard_a.release (); notify_observers_callback (cemented_blocks); @@ -448,7 +429,7 @@ std::shared_ptr nano::confirmation_height_unbounded::get_block_and_ } else { - auto block (ledger.store.block.get (transaction_a, hash_a)); + auto block = ledger.block (transaction_a, hash_a); block_cache.emplace (hash_a, block); return block; } diff --git a/nano/node/confirmation_height_unbounded.hpp b/nano/node/confirmation_height_unbounded.hpp index 0af353e69a..ea3e7e52a1 100644 --- a/nano/node/confirmation_height_unbounded.hpp +++ b/nano/node/confirmation_height_unbounded.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -12,15 +13,14 @@ namespace nano { class ledger; -class logging; -class logger_mt; class write_database_queue; class write_guard; class confirmation_height_unbounded final { public: - confirmation_height_unbounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logging const &, nano::logger_mt &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); + confirmation_height_unbounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds batch_separate_pending_min_time, nano::logger &, std::atomic & stopped, uint64_t & batch_write_size, std::function> const &)> const & cemented_callback, std::function const & already_cemented_callback, std::function const & awaiting_processing_size_query); + bool pending_empty () const; void clear_process_vars (); void process (std::shared_ptr original_block); @@ -98,10 +98,9 @@ class confirmation_height_unbounded final nano::ledger & ledger; nano::write_database_queue & write_database_queue; std::chrono::milliseconds batch_separate_pending_min_time; - nano::logger_mt & logger; + nano::logger & logger; std::atomic & stopped; uint64_t & batch_write_size; - nano::logging const & logging; std::function> const &)> notify_observers_callback; std::function notify_block_already_cemented_observers_callback; diff --git a/nano/node/confirmation_solicitor.cpp b/nano/node/confirmation_solicitor.cpp index cece99c530..feb782453a 100644 --- a/nano/node/confirmation_solicitor.cpp +++ b/nano/node/confirmation_solicitor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/node/distributed_work.cpp b/nano/node/distributed_work.cpp index b710c41552..3f2ffcb2d7 100644 --- a/nano/node/distributed_work.cpp +++ b/nano/node/distributed_work.cpp @@ -68,7 +68,7 @@ void nano::distributed_work::start () else if (need_resolve.empty () && request.callback) { status = work_generation_status::failure_local; - request.callback (boost::none); + request.callback (std::nullopt); } for (auto const & peer : need_resolve) { @@ -94,7 +94,8 @@ void nano::distributed_work::start () } else { - this_l->node.logger.try_log (boost::str (boost::format ("Error resolving work peer: %1%:%2%: %3%") % peer.first % peer.second % ec.message ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Error resolving work peer: {}:{} ({})", peer.first, peer.second, ec.message ()); + this_l->failure (); } }); @@ -116,7 +117,7 @@ void nano::distributed_work::start_local () this_l->status = work_generation_status::failure_local; if (this_l->request.callback) { - this_l->request.callback (boost::none); + this_l->request.callback (std::nullopt); } } this_l->stop_once (false); @@ -142,9 +143,9 @@ void nano::distributed_work::do_request (nano::tcp_endpoint const & endpoint_a) rpc_request.put ("action", "work_generate"); rpc_request.put ("hash", this_l->request.root.to_string ()); rpc_request.put ("difficulty", nano::to_string_hex (this_l->request.difficulty)); - if (this_l->request.account.is_initialized ()) + if (this_l->request.account.has_value ()) { - rpc_request.put ("account", this_l->request.account.get ().to_account ()); + rpc_request.put ("account", this_l->request.account.value ().to_account ()); } std::stringstream ostream; boost::property_tree::write_json (ostream, rpc_request); @@ -166,7 +167,11 @@ void nano::distributed_work::do_request (nano::tcp_endpoint const & endpoint_a) } else if (ec) { - this_l->node.logger.try_log (boost::str (boost::format ("Work peer responded with an error %1% %2%: %3%") % connection->endpoint.address () % connection->endpoint.port () % connection->response.result ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Work peer responded with an error {}:{} ({})", + nano::util::to_str (connection->endpoint.address ()), + connection->endpoint.port (), + ec.message ()); + this_l->add_bad_peer (connection->endpoint); this_l->failure (); } @@ -180,7 +185,11 @@ void nano::distributed_work::do_request (nano::tcp_endpoint const & endpoint_a) } else if (ec && ec != boost::system::errc::operation_canceled) { - this_l->node.logger.try_log (boost::str (boost::format ("Unable to write to work_peer %1% %2%: %3% (%4%)") % connection->endpoint.address () % connection->endpoint.port () % ec.message () % ec.value ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Unable to write to work peer {}:{} ({})", + nano::util::to_str (connection->endpoint.address ()), + connection->endpoint.port (), + ec.message ()); + this_l->add_bad_peer (connection->endpoint); this_l->failure (); } @@ -188,7 +197,11 @@ void nano::distributed_work::do_request (nano::tcp_endpoint const & endpoint_a) } else if (ec && ec != boost::system::errc::operation_canceled) { - this_l->node.logger.try_log (boost::str (boost::format ("Unable to connect to work_peer %1% %2%: %3% (%4%)") % connection->endpoint.address () % connection->endpoint.port () % ec.message () % ec.value ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Unable to connect to work peer {}:{} ({})", + nano::util::to_str (connection->endpoint.address ()), + connection->endpoint.port (), + ec.message ()); + this_l->add_bad_peer (connection->endpoint); this_l->failure (); } @@ -219,7 +232,10 @@ void nano::distributed_work::do_cancel (nano::tcp_endpoint const & endpoint_a) [this_l, peer_cancel, cancelling_l] (boost::system::error_code const & ec, std::size_t bytes_transferred) { if (ec && ec != boost::system::errc::operation_canceled) { - this_l->node.logger.try_log (boost::str (boost::format ("Unable to send work_cancel to work_peer %1% %2%: %3% (%4%)") % cancelling_l->endpoint.address () % cancelling_l->endpoint.port () % ec.message () % ec.value ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Unable to send work cancel to work peer {}:{} ({})", + nano::util::to_str (cancelling_l->endpoint.address ()), + cancelling_l->endpoint.port (), + ec.message ()); } })); } @@ -247,17 +263,28 @@ void nano::distributed_work::success (std::string const & body_a, nano::tcp_endp } else { - node.logger.try_log (boost::str (boost::format ("Incorrect work response from %1%:%2% for root %3% with diffuculty %4%: %5%") % endpoint_a.address () % endpoint_a.port () % request.root.to_string () % nano::to_string_hex (request.difficulty) % work_text)); + node.logger.error (nano::log::type::distributed_work, "Incorrect work response from {}:{} for root {} with diffuculty {}: {}", + nano::util::to_str (endpoint_a.address ()), + endpoint_a.port (), + request.root.to_string (), + nano::to_string_hex (request.difficulty), + work_text); } } else { - node.logger.try_log (boost::str (boost::format ("Work response from %1%:%2% wasn't a number: %3%") % endpoint_a.address () % endpoint_a.port () % work_text)); + node.logger.error (nano::log::type::distributed_work, "Work response from {}:{} wasn't a number: {}", + nano::util::to_str (endpoint_a.address ()), + endpoint_a.port (), + work_text); } } catch (...) { - node.logger.try_log (boost::str (boost::format ("Work response from %1%:%2% wasn't parsable: %3%") % endpoint_a.address () % endpoint_a.port () % body_a)); + node.logger.error (nano::log::type::distributed_work, "Work response from {}:{} wasn't parsable: {}", + nano::util::to_str (endpoint_a.address ()), + endpoint_a.port (), + body_a); } if (error) { @@ -290,12 +317,18 @@ void nano::distributed_work::stop_once (bool const local_stop_a) connection_l->socket.close (ec); if (ec) { - this_l->node.logger.try_log (boost::str (boost::format ("Error closing socket with work_peer %1% %2%: %3%") % connection_l->endpoint.address () % connection_l->endpoint.port () % ec.message () % ec.value ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Error closing socket with work peer: {}:{} ({})", + nano::util::to_str (connection_l->endpoint.address ()), + connection_l->endpoint.port (), + ec.message ()); } } else { - this_l->node.logger.try_log (boost::str (boost::format ("Error cancelling operation with work_peer %1% %2%: %3%") % connection_l->endpoint.address () % connection_l->endpoint.port () % ec.message () % ec.value ())); + this_l->node.logger.error (nano::log::type::distributed_work, "Error cancelling operation with work peer: {}:{} ({})", + nano::util::to_str (connection_l->endpoint.address ()), + connection_l->endpoint.port (), + ec.message ()); } } })); @@ -310,6 +343,13 @@ void nano::distributed_work::set_once (uint64_t const work_a, std::string const if (!finished.exchange (true)) { elapsed.stop (); + + node.logger.info (nano::log::type::distributed_work, "Work generation for {}, with a threshold difficulty of {} (multiplier {}x) complete: {} ms", + request.root.to_string (), + nano::to_string_hex (request.difficulty), + nano::to_string (nano::difficulty::to_multiplier (request.difficulty, node.default_difficulty (request.version)), 2), + elapsed.value ().count ()); + status = work_generation_status::success; if (request.callback) { @@ -317,12 +357,6 @@ void nano::distributed_work::set_once (uint64_t const work_a, std::string const } winner = source_a; work_result = work_a; - if (node.config.logging.work_generation_time ()) - { - boost::format unformatted_l ("Work generation for %1%, with a threshold difficulty of %2% (multiplier %3%x) complete: %4% ms"); - auto multiplier_text_l (nano::to_string (nano::difficulty::to_multiplier (request.difficulty, node.default_difficulty (request.version)), 2)); - node.logger.try_log (boost::str (unformatted_l % request.root.to_string () % nano::to_string_hex (request.difficulty) % multiplier_text_l % elapsed.value ().count ())); - } } } @@ -331,16 +365,17 @@ void nano::distributed_work::cancel () if (!finished.exchange (true)) { elapsed.stop (); + + node.logger.info (nano::log::type::distributed_work, "Work generation for {} was cancelled after {} ms", + request.root.to_string (), + elapsed.value ().count ()); + status = work_generation_status::cancelled; if (request.callback) { - request.callback (boost::none); + request.callback (std::nullopt); } stop_once (true); - if (node.config.logging.work_generation_time ()) - { - node.logger.try_log (boost::str (boost::format ("Work generation for %1% was cancelled after %2% ms") % request.root.to_string () % elapsed.value ().count ())); - } } } @@ -359,11 +394,12 @@ void nano::distributed_work::handle_failure () node.unresponsive_work_peers = true; if (!local_generation_started && !finished.exchange (true)) { + node.logger.info (nano::log::type::distributed_work, "Work peer(s) failed to generate work for root {}, retrying... (backoff: {}s)", + request.root.to_string (), + backoff.count ()); + status = work_generation_status::failure_peers; - if (backoff == std::chrono::seconds (1) && node.config.logging.work_generation_time ()) - { - node.logger.always_log ("Work peer(s) failed to generate work for root ", request.root.to_string (), ", retrying..."); - } + auto now (std::chrono::steady_clock::now ()); std::weak_ptr node_weak (node.shared ()); auto next_backoff (std::min (backoff * 2, std::chrono::seconds (5 * 60))); @@ -375,7 +411,7 @@ void nano::distributed_work::handle_failure () } if (error_l && request_l.callback) { - request_l.callback (boost::none); + request_l.callback (std::nullopt); } }); } diff --git a/nano/node/distributed_work.hpp b/nano/node/distributed_work.hpp index e8772b3c63..17edecc60b 100644 --- a/nano/node/distributed_work.hpp +++ b/nano/node/distributed_work.hpp @@ -9,6 +9,8 @@ #include #include +#include + using request_type = boost::beast::http::request; namespace boost @@ -28,8 +30,8 @@ struct work_request final nano::work_version version; nano::root root; uint64_t difficulty; - boost::optional const account; - std::function)> callback; + std::optional const account; + std::function)> callback; std::vector> const peers; }; @@ -107,4 +109,4 @@ class distributed_work final : public std::enable_shared_from_this stopped{ false }; std::atomic local_generation_started{ false }; }; -} \ No newline at end of file +} diff --git a/nano/node/distributed_work_factory.cpp b/nano/node/distributed_work_factory.cpp index 2fd41aaf5a..a0c1ac64cc 100644 --- a/nano/node/distributed_work_factory.cpp +++ b/nano/node/distributed_work_factory.cpp @@ -12,7 +12,7 @@ nano::distributed_work_factory::~distributed_work_factory () stop (); } -bool nano::distributed_work_factory::make (nano::work_version const version_a, nano::root const & root_a, std::vector> const & peers_a, uint64_t difficulty_a, std::function)> const & callback_a, boost::optional const & account_a) +bool nano::distributed_work_factory::make (nano::work_version const version_a, nano::root const & root_a, std::vector> const & peers_a, uint64_t difficulty_a, std::function)> const & callback_a, std::optional const & account_a) { return make (std::chrono::seconds (1), nano::work_request{ version_a, root_a, difficulty_a, account_a, callback_a, peers_a }); } diff --git a/nano/node/distributed_work_factory.hpp b/nano/node/distributed_work_factory.hpp index ae626ead0e..97c697aa9e 100644 --- a/nano/node/distributed_work_factory.hpp +++ b/nano/node/distributed_work_factory.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -20,7 +21,7 @@ class distributed_work_factory final public: distributed_work_factory (nano::node &); ~distributed_work_factory (); - bool make (nano::work_version const, nano::root const &, std::vector> const &, uint64_t, std::function)> const &, boost::optional const & = boost::none); + bool make (nano::work_version const, nano::root const &, std::vector> const &, uint64_t, std::function)> const &, std::optional const & = std::nullopt); bool make (std::chrono::seconds const &, nano::work_request const &); void cancel (nano::root const &); void cleanup_finished (); diff --git a/nano/node/election.cpp b/nano/node/election.cpp index 93c681c706..9dda840329 100644 --- a/nano/node/election.cpp +++ b/nano/node/election.cpp @@ -1,10 +1,14 @@ +#include #include #include #include #include +#include #include +#include + using namespace std::chrono; std::chrono::milliseconds nano::election::base_latency () const @@ -18,6 +22,10 @@ nano::election_vote_result::election_vote_result (bool replay_a, bool processed_ processed = processed_a; } +/* + * election + */ + nano::election::election (nano::node & node_a, std::shared_ptr const & block_a, std::function const &)> const & confirmation_action_a, std::function const & live_vote_action_a, nano::election_behavior election_behavior_a) : confirmation_action (confirmation_action_a), live_vote_action (live_vote_action_a), @@ -54,6 +62,11 @@ void nano::election::confirm_once (nano::unique_lock & lock_a, nano node.active.recently_confirmed.put (qualified_root, status_l.winner->hash ()); + node.logger.trace (nano::log::type::election, nano::log::detail::election_confirmed, + nano::log::arg{ "id", id }, + nano::log::arg{ "qualified_root", qualified_root }, + nano::log::arg{ "status", current_status_locked () }); + lock_a.unlock (); node.background ([node_l = node.shared (), status_l, confirmation_action_l = confirmation_action] () { @@ -163,16 +176,16 @@ void nano::election::transition_active () state_change (nano::election::state_t::passive, nano::election::state_t::active); } -bool nano::election::confirmed_locked (nano::unique_lock & lock) const +bool nano::election::confirmed_locked () const { - debug_assert (lock.owns_lock ()); + debug_assert (!mutex.try_lock ()); return state_m == nano::election::state_t::confirmed || state_m == nano::election::state_t::expired_confirmed; } bool nano::election::confirmed () const { nano::unique_lock lock{ mutex }; - return confirmed_locked (lock); + return confirmed_locked (); } bool nano::election::failed () const @@ -181,13 +194,35 @@ bool nano::election::failed () const return state_m == nano::election::state_t::expired_unconfirmed; } +bool nano::election::broadcast_block_predicate () const +{ + debug_assert (!mutex.try_lock ()); + + // Broadcast the block if enough time has passed since the last broadcast (or it's the first broadcast) + if (last_block + node.config.network_params.network.block_broadcast_interval < std::chrono::steady_clock::now ()) + { + return true; + } + // Or the current election winner has changed + if (status.winner->hash () != last_block_hash) + { + return true; + } + return false; +} + void nano::election::broadcast_block (nano::confirmation_solicitor & solicitor_a) { - if (base_latency () * 15 < std::chrono::steady_clock::now () - last_block) + debug_assert (!mutex.try_lock ()); + + if (broadcast_block_predicate ()) { if (!solicitor_a.broadcast (*this)) { + node.stats.inc (nano::stat::type::election, last_block_hash.is_zero () ? nano::stat::detail::broadcast_block_initial : nano::stat::detail::broadcast_block_repeat); + last_block = std::chrono::steady_clock::now (); + last_block_hash = status.winner->hash (); } } } @@ -235,6 +270,7 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a break; case nano::election::state_t::confirmed: result = true; // Return true to indicate this election should be cleaned up + broadcast_block (solicitor_a); // Ensure election winner is broadcasted state_change (nano::election::state_t::confirmed, nano::election::state_t::expired_confirmed); break; case nano::election::state_t::expired_unconfirmed: @@ -243,17 +279,18 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a break; } - if (!confirmed_locked (lock) && time_to_live () < std::chrono::steady_clock::now () - election_start) + if (!confirmed_locked () && time_to_live () < std::chrono::steady_clock::now () - election_start) { // It is possible the election confirmed while acquiring the mutex // state_change returning true would indicate it if (!state_change (state_m, nano::election::state_t::expired_unconfirmed)) { + node.logger.trace (nano::log::type::election, nano::log::detail::election_expired, + nano::log::arg{ "id", id }, + nano::log::arg{ "qualified_root", qualified_root }, + nano::log::arg{ "status", current_status_locked () }); + result = true; // Return true to indicate this election should be cleaned up - if (node.config.logging.election_expiration_tally_logging ()) - { - log_votes (tally_impl (), "Election expired: "); - } status.type = nano::election_status_type::stopped; } } @@ -368,17 +405,10 @@ void nano::election::confirm_if_quorum (nano::unique_lock & lock_a) { if (node.ledger.cache.final_votes_confirmation_canary.load () && !is_quorum.exchange (true) && node.config.enable_voting && node.wallets.reps ().voting > 0) { - auto hash = status.winner->hash (); - lock_a.unlock (); - node.final_generator.add (root, hash); - lock_a.lock (); + node.final_generator.add (root, status.winner->hash ()); } if (!node.ledger.cache.final_votes_confirmation_canary.load () || final_weight >= node.online_reps.delta ()) { - if (node.config.logging.vote_logging () || (node.config.logging.election_fork_tally_logging () && last_blocks.size () > 1)) - { - log_votes (tally_l); - } confirm_once (lock_a, nano::election_status_type::active_confirmed_quorum); } } @@ -392,7 +422,7 @@ boost::optional nano::election::try_confirm (nano::b if (winner && winner->hash () == hash) { // Determine if the block was confirmed explicitly via election confirmation or implicitly via confirmation height - if (!confirmed_locked (election_lock)) + if (!confirmed_locked ()) { confirm_once (election_lock, nano::election_status_type::active_confirmation_height); status_type = nano::election_status_type::active_confirmation_height; @@ -419,25 +449,6 @@ nano::election_status nano::election::set_status_type (nano::election_status_typ return status_l; } -void nano::election::log_votes (nano::tally_t const & tally_a, std::string const & prefix_a) const -{ - std::stringstream tally; - std::string line_end (node.config.logging.single_line_record () ? "\t" : "\n"); - tally << boost::str (boost::format ("%1%%2%Vote tally for root %3%, final weight:%4%") % prefix_a % line_end % root.to_string () % final_weight); - for (auto i (tally_a.begin ()), n (tally_a.end ()); i != n; ++i) - { - tally << boost::str (boost::format ("%1%Block %2% weight %3%") % line_end % i->second->hash ().to_string () % i->first.convert_to ()); - } - for (auto i (last_votes.begin ()), n (last_votes.end ()); i != n; ++i) - { - if (i->first != nullptr) - { - tally << boost::str (boost::format ("%1%%2% %3% %4%") % line_end % i->first.to_account () % std::to_string (i->second.timestamp) % i->second.hash.to_string ()); - } - } - node.logger.try_log (tally.str ()); -} - std::shared_ptr nano::election::find (nano::block_hash const & hash_a) const { std::shared_ptr result; @@ -486,6 +497,7 @@ nano::election_vote_result nano::election::vote (nano::account const & rep, uint return nano::election_vote_result (false, false); } } + last_votes[rep] = { std::chrono::steady_clock::now (), timestamp_a, block_hash_a }; if (vote_source_a == vote_source::live) { @@ -493,8 +505,17 @@ nano::election_vote_result nano::election::vote (nano::account const & rep, uint } node.stats.inc (nano::stat::type::election, vote_source_a == vote_source::live ? nano::stat::detail::vote_new : nano::stat::detail::vote_cached); - - if (!confirmed_locked (lock)) + node.logger.trace (nano::log::type::election, nano::log::detail::vote_processed, + nano::log::arg{ "id", id }, + nano::log::arg{ "qualified_root", qualified_root }, + nano::log::arg{ "account", rep }, + nano::log::arg{ "hash", block_hash_a }, + nano::log::arg{ "final", nano::vote::is_final_timestamp (timestamp_a) }, + nano::log::arg{ "timestamp", timestamp_a }, + nano::log::arg{ "vote_source", vote_source_a }, + nano::log::arg{ "weight", weight }); + + if (!confirmed_locked ()) { confirm_if_quorum (lock); } @@ -506,7 +527,7 @@ bool nano::election::publish (std::shared_ptr const & block_a) nano::unique_lock lock{ mutex }; // Do not insert new blocks if already confirmed - auto result (confirmed_locked (lock)); + auto result (confirmed_locked ()); if (!result && last_blocks.size () >= max_blocks && last_blocks.find (block_a->hash ()) == last_blocks.end ()) { if (!replace_by_weight (lock, block_a->hash ())) @@ -546,11 +567,18 @@ bool nano::election::publish (std::shared_ptr const & block_a) nano::election_extended_status nano::election::current_status () const { nano::lock_guard guard{ mutex }; + return current_status_locked (); +} + +nano::election_extended_status nano::election::current_status_locked () const +{ + debug_assert (!mutex.try_lock ()); + nano::election_status status_l = status; status_l.confirmation_request_count = confirmation_request_count; status_l.block_count = nano::narrow_cast (last_blocks.size ()); status_l.voter_count = nano::narrow_cast (last_votes.size ()); - return nano::election_extended_status{ status_l, last_votes, tally_impl () }; + return nano::election_extended_status{ status_l, last_votes, last_blocks, tally_impl () }; } std::shared_ptr nano::election::winner () const @@ -563,23 +591,36 @@ void nano::election::broadcast_vote_locked (nano::unique_lock & loc { debug_assert (lock.owns_lock ()); - if (std::chrono::steady_clock::now () < last_vote + std::chrono::milliseconds (node.config.network_params.network.vote_broadcast_interval)) + if (std::chrono::steady_clock::now () < last_vote + node.config.network_params.network.vote_broadcast_interval) { return; } last_vote = std::chrono::steady_clock::now (); + if (node.config.enable_voting && node.wallets.reps ().voting > 0) { - node.stats.inc (nano::stat::type::election, nano::stat::detail::generate_vote); + node.stats.inc (nano::stat::type::election, nano::stat::detail::broadcast_vote); - if (confirmed_locked (lock) || have_quorum (tally_impl ())) + if (confirmed_locked () || have_quorum (tally_impl ())) { - node.stats.inc (nano::stat::type::election, nano::stat::detail::generate_vote_final); + node.stats.inc (nano::stat::type::election, nano::stat::detail::broadcast_vote_final); + node.logger.trace (nano::log::type::election, nano::log::detail::broadcast_vote, + nano::log::arg{ "id", id }, + nano::log::arg{ "qualified_root", qualified_root }, + nano::log::arg{ "winner", status.winner }, + nano::log::arg{ "type", "final" }); + node.final_generator.add (root, status.winner->hash ()); // Broadcasts vote to the network } else { - node.stats.inc (nano::stat::type::election, nano::stat::detail::generate_vote_normal); + node.stats.inc (nano::stat::type::election, nano::stat::detail::broadcast_vote_normal); + node.logger.trace (nano::log::type::election, nano::log::detail::broadcast_vote, + nano::log::arg{ "id", id }, + nano::log::arg{ "qualified_root", qualified_root }, + nano::log::arg{ "winner", status.winner }, + nano::log::arg{ "type", "normal" }); + node.generator.add (root, status.winner->hash ()); // Broadcasts vote to the network } } @@ -608,17 +649,10 @@ void nano::election::remove_block (nano::block_hash const & hash_a) { if (auto existing = last_blocks.find (hash_a); existing != last_blocks.end ()) { - for (auto i (last_votes.begin ()); i != last_votes.end ();) - { - if (i->second.hash == hash_a) - { - i = last_votes.erase (i); - } - else - { - ++i; - } - } + erase_if (last_votes, [hash_a] (auto const & entry) { + return entry.second.hash == hash_a; + }); + node.network.publish_filter.clear (existing->second); last_blocks.erase (hash_a); } @@ -720,27 +754,53 @@ std::vector nano::election::votes_with_weight () co nano::stat::detail nano::to_stat_detail (nano::election_behavior behavior) { - switch (behavior) - { - case nano::election_behavior::normal: - { - return nano::stat::detail::normal; - } - case nano::election_behavior::hinted: - { - return nano::stat::detail::hinted; - } - case nano::election_behavior::optimistic: - { - return nano::stat::detail::optimistic; - } - } - - debug_assert (false, "unknown election behavior"); - return {}; + auto value = magic_enum::enum_cast (magic_enum::enum_name (behavior)); + debug_assert (value); + return value.value_or (nano::stat::detail{}); } nano::election_behavior nano::election::behavior () const { return behavior_m; } + +// TODO: Remove the need for .to_string () calls +void nano::election::operator() (nano::object_stream & obs) const +{ + obs.write ("id", id); + obs.write ("qualified_root", qualified_root.to_string ()); + obs.write ("behaviour", behavior_m); + obs.write ("height", height); + obs.write ("status", current_status ()); +} + +void nano::election_extended_status::operator() (nano::object_stream & obs) const +{ + obs.write ("winner", status.winner->hash ().to_string ()); + obs.write ("tally_amount", status.tally.to_string_dec ()); + obs.write ("final_tally_amount", status.final_tally.to_string_dec ()); + obs.write ("confirmation_request_count", status.confirmation_request_count); + obs.write ("block_count", status.block_count); + obs.write ("voter_count", status.voter_count); + obs.write ("type", status.type); + + obs.write_range ("votes", votes, [] (auto const & entry, nano::object_stream & obs) { + auto & [account, info] = entry; + obs.write ("account", account.to_account ()); + obs.write ("hash", info.hash.to_string ()); + obs.write ("final", nano::vote::is_final_timestamp (info.timestamp)); + obs.write ("timestamp", info.timestamp); + obs.write ("time", info.time.time_since_epoch ().count ()); + }); + + obs.write_range ("blocks", blocks, [] (auto const & entry) { + auto [hash, block] = entry; + return block; + }); + + obs.write_range ("tally", tally, [] (auto const & entry, nano::object_stream & obs) { + auto & [amount, block] = entry; + obs.write ("hash", block->hash ().to_string ()); + obs.write ("amount", amount); + }); +} diff --git a/nano/node/election.hpp b/nano/node/election.hpp index b49f946540..258c5655e2 100644 --- a/nano/node/election.hpp +++ b/nano/node/election.hpp @@ -1,7 +1,8 @@ #pragma once +#include +#include #include -#include #include #include @@ -62,15 +63,23 @@ enum class election_behavior nano::stat::detail to_stat_detail (nano::election_behavior); +// map of vote weight per block, ordered greater first +using tally_t = std::map, std::greater>; + struct election_extended_status final { nano::election_status status; std::unordered_map votes; + std::unordered_map> blocks; nano::tally_t tally; + + void operator() (nano::object_stream &) const; }; class election final : public std::enable_shared_from_this { + nano::id_t const id{ nano::next_id () }; // Track individual objects when tracing + public: enum class vote_source { @@ -101,10 +110,11 @@ class election final : public std::enable_shared_from_this std::chrono::steady_clock::duration state_start{ std::chrono::steady_clock::now ().time_since_epoch () }; // These are modified while not holding the mutex from transition_time only - std::chrono::steady_clock::time_point last_block = { std::chrono::steady_clock::now () }; - std::chrono::steady_clock::time_point last_req = {}; + std::chrono::steady_clock::time_point last_block{}; + nano::block_hash last_block_hash{ 0 }; + std::chrono::steady_clock::time_point last_req{}; /** The last time vote for this election was generated */ - std::chrono::steady_clock::time_point last_vote = {}; + std::chrono::steady_clock::time_point last_vote{}; bool valid_change (nano::election::state_t, nano::election::state_t) const; bool state_change (nano::election::state_t, nano::election::state_t); @@ -120,7 +130,6 @@ class election final : public std::enable_shared_from_this std::shared_ptr winner () const; std::atomic confirmation_request_count{ 0 }; - void log_votes (nano::tally_t const &, std::string const & = "") const; nano::tally_t tally () const; bool have_quorum (nano::tally_t const &) const; @@ -163,9 +172,11 @@ class election final : public std::enable_shared_from_this private: nano::tally_t tally_impl () const; - bool confirmed_locked (nano::unique_lock & lock) const; + bool confirmed_locked () const; + nano::election_extended_status current_status_locked () const; // lock_a does not own the mutex on return void confirm_once (nano::unique_lock & lock_a, nano::election_status_type = nano::election_status_type::active_confirmed_quorum); + bool broadcast_block_predicate () const; void broadcast_block (nano::confirmation_solicitor &); void send_confirm_req (nano::confirmation_solicitor &); /** @@ -198,6 +209,9 @@ class election final : public std::enable_shared_from_this mutable nano::mutex mutex; +public: // Logging + void operator() (nano::object_stream &) const; + private: // Constants static std::size_t constexpr max_blocks{ 10 }; diff --git a/nano/node/epoch_upgrader.cpp b/nano/node/epoch_upgrader.cpp index a731bb4da8..58db6213d0 100644 --- a/nano/node/epoch_upgrader.cpp +++ b/nano/node/epoch_upgrader.cpp @@ -1,8 +1,10 @@ +#include #include #include #include +#include -nano::epoch_upgrader::epoch_upgrader (nano::node & node_a, nano::ledger & ledger_a, nano::store::component & store_a, nano::network_params & network_params_a, nano::logger_mt & logger_a) : +nano::epoch_upgrader::epoch_upgrader (nano::node & node_a, nano::ledger & ledger_a, nano::store::component & store_a, nano::network_params & network_params_a, nano::logger & logger_a) : node{ node_a }, ledger{ ledger_a }, store{ store_a }, @@ -47,19 +49,24 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc epoch->block_work_set (node.work_generate_blocking (nano::work_version::work_1, root_a, difficulty).value_or (0)); bool valid_signature (!nano::validate_message (signer_a, epoch->hash (), epoch->block_signature ())); bool valid_work (node.network_params.work.difficulty (*epoch) >= difficulty); - nano::process_result result (nano::process_result::old); + nano::block_status result (nano::block_status::old); if (valid_signature && valid_work) { - result = node.process_local (epoch).value ().code; + result = node.process_local (epoch).value (); } - if (result == nano::process_result::progress) + if (result == nano::block_status::progress) { ++counter; } else { - bool fork (result == nano::process_result::fork); - logger.always_log (boost::str (boost::format ("Failed to upgrade account %1%. Valid signature: %2%. Valid work: %3%. Block processor fork: %4%") % account_a.to_account () % valid_signature % valid_work % fork)); + bool fork (result == nano::block_status::fork); + + logger.error (nano::log::type::epoch_upgrader, "Failed to upgrade account {} (valid signature: {}, valid work: {}, fork: {})", + account_a.to_account (), + valid_signature, + valid_work, + fork); } }; @@ -181,12 +188,16 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc if (!accounts_list.empty ()) { - logger.always_log (boost::str (boost::format ("%1% accounts were upgraded to new epoch, %2% remain...") % total_upgraded_accounts % (accounts_list.size () - upgraded_accounts))); + logger.info (nano::log::type::epoch_upgrader, "{} accounts were upgraded to new epoch, {} remain...", + total_upgraded_accounts, + accounts_list.size () - upgraded_accounts); + accounts_list.clear (); } else { - logger.always_log (boost::str (boost::format ("%1% total accounts were upgraded to new epoch") % total_upgraded_accounts)); + logger.info (nano::log::type::epoch_upgrader, "{} total accounts were upgraded to new epoch", total_upgraded_accounts); + finished_accounts = true; } } @@ -284,11 +295,12 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc // Repeat if some pending accounts were upgraded if (upgraded_pending != 0) { - logger.always_log (boost::str (boost::format ("%1% unopened accounts with pending blocks were upgraded to new epoch...") % total_upgraded_pending)); + logger.info (nano::log::type::epoch_upgrader, "{} unopened accounts with pending blocks were upgraded to new epoch...", total_upgraded_pending); } else { - logger.always_log (boost::str (boost::format ("%1% total unopened accounts with pending blocks were upgraded to new epoch") % total_upgraded_pending)); + logger.info (nano::log::type::epoch_upgrader, "{} total unopened accounts with pending blocks were upgraded to new epoch", total_upgraded_pending); + finished_pending = true; } } @@ -296,5 +308,5 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc finished_upgrade = (total_upgraded_accounts == 0) && (total_upgraded_pending == 0); } - logger.always_log ("Epoch upgrade is completed"); + logger.info (nano::log::type::epoch_upgrader, "Epoch upgrade is completed"); } diff --git a/nano/node/epoch_upgrader.hpp b/nano/node/epoch_upgrader.hpp index ab0499fb14..d9bccad98e 100644 --- a/nano/node/epoch_upgrader.hpp +++ b/nano/node/epoch_upgrader.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -15,12 +16,11 @@ namespace store class component; } class network_params; -class logger_mt; class epoch_upgrader final { public: - epoch_upgrader (nano::node &, nano::ledger &, nano::store::component &, nano::network_params &, nano::logger_mt &); + epoch_upgrader (nano::node &, nano::ledger &, nano::store::component &, nano::network_params &, nano::logger &); bool start (nano::raw_key const & prv, nano::epoch epoch, uint64_t count_limit, uint64_t threads); void stop (); @@ -30,7 +30,7 @@ class epoch_upgrader final nano::ledger & ledger; nano::store::component & store; nano::network_params & network_params; - nano::logger_mt & logger; + nano::logger & logger; private: void upgrade_impl (nano::raw_key const & prv, nano::epoch epoch, uint64_t count_limit, uint64_t threads); diff --git a/nano/node/gap_cache.cpp b/nano/node/gap_cache.cpp deleted file mode 100644 index 0153455810..0000000000 --- a/nano/node/gap_cache.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include - -#include - -nano::gap_cache::gap_cache (nano::node & node_a) : - node (node_a) -{ -} - -void nano::gap_cache::add (nano::block_hash const & hash_a, std::chrono::steady_clock::time_point time_point_a) -{ - nano::lock_guard lock{ mutex }; - auto existing (blocks.get ().find (hash_a)); - if (existing != blocks.get ().end ()) - { - blocks.get ().modify (existing, [time_point_a] (nano::gap_information & info) { - info.arrival = time_point_a; - }); - } - else - { - blocks.get ().emplace (nano::gap_information{ time_point_a, hash_a, std::vector () }); - if (blocks.get ().size () > max) - { - blocks.get ().erase (blocks.get ().begin ()); - } - } -} - -void nano::gap_cache::erase (nano::block_hash const & hash_a) -{ - nano::lock_guard lock{ mutex }; - blocks.get ().erase (hash_a); -} - -void nano::gap_cache::vote (std::shared_ptr const & vote_a) -{ - nano::lock_guard lock{ mutex }; - for (auto const & hash : vote_a->hashes) - { - auto & gap_blocks_by_hash (blocks.get ()); - auto existing (gap_blocks_by_hash.find (hash)); - if (existing != gap_blocks_by_hash.end () && !existing->bootstrap_started) - { - auto is_new (false); - gap_blocks_by_hash.modify (existing, [&is_new, &vote_a] (nano::gap_information & info) { - auto it = std::find (info.voters.begin (), info.voters.end (), vote_a->account); - is_new = (it == info.voters.end ()); - if (is_new) - { - info.voters.push_back (vote_a->account); - } - }); - - if (is_new) - { - if (bootstrap_check (existing->voters, hash)) - { - gap_blocks_by_hash.modify (existing, [] (nano::gap_information & info) { - info.bootstrap_started = true; - }); - } - } - } - } -} - -bool nano::gap_cache::bootstrap_check (std::vector const & voters_a, nano::block_hash const & hash_a) -{ - nano::uint128_t tally; - for (auto const & voter : voters_a) - { - tally += node.ledger.weight (voter); - } - bool start_bootstrap (false); - if (!node.flags.disable_lazy_bootstrap) - { - if (tally >= node.online_reps.delta ()) - { - start_bootstrap = true; - } - } - else if (!node.flags.disable_legacy_bootstrap && tally > bootstrap_threshold ()) - { - start_bootstrap = true; - } - if (start_bootstrap && !node.ledger.block_or_pruned_exists (hash_a)) - { - bootstrap_start (hash_a); - } - return start_bootstrap; -} - -void nano::gap_cache::bootstrap_start (nano::block_hash const & hash_a) -{ - auto node_l (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + node.network_params.bootstrap.gap_cache_bootstrap_start_interval, [node_l, hash_a] () { - if (!node_l->ledger.block_or_pruned_exists (hash_a)) - { - if (!node_l->bootstrap_initiator.in_progress ()) - { - node_l->logger.try_log (boost::str (boost::format ("Missing block %1% which has enough votes to warrant lazy bootstrapping it") % hash_a.to_string ())); - } - if (!node_l->flags.disable_lazy_bootstrap) - { - node_l->bootstrap_initiator.bootstrap_lazy (hash_a); - } - else if (!node_l->flags.disable_legacy_bootstrap) - { - node_l->bootstrap_initiator.bootstrap (); - } - } - }); -} - -nano::uint128_t nano::gap_cache::bootstrap_threshold () -{ - auto result ((node.online_reps.trended () / 256) * node.config.bootstrap_fraction_numerator); - return result; -} - -std::size_t nano::gap_cache::size () -{ - nano::lock_guard lock{ mutex }; - return blocks.size (); -} - -std::unique_ptr nano::collect_container_info (gap_cache & gap_cache, std::string const & name) -{ - auto count = gap_cache.size (); - auto sizeof_element = sizeof (decltype (gap_cache.blocks)::value_type); - auto composite = std::make_unique (name); - composite->add_component (std::make_unique (container_info{ "blocks", count, sizeof_element })); - return composite; -} diff --git a/nano/node/gap_cache.hpp b/nano/node/gap_cache.hpp deleted file mode 100644 index 118625fd35..0000000000 --- a/nano/node/gap_cache.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -namespace nano -{ -class node; - -/** For each gap in account chains, track arrival time and voters */ -class gap_information final -{ -public: - std::chrono::steady_clock::time_point arrival; - nano::block_hash hash; - std::vector voters; - bool bootstrap_started{ false }; -}; - -/** Maintains voting and arrival information for gaps (missing source or previous blocks in account chains) */ -class gap_cache final -{ -public: - explicit gap_cache (nano::node &); - void add (nano::block_hash const &, std::chrono::steady_clock::time_point = std::chrono::steady_clock::now ()); - void erase (nano::block_hash const & hash_a); - void vote (std::shared_ptr const &); - bool bootstrap_check (std::vector const &, nano::block_hash const &); - void bootstrap_start (nano::block_hash const & hash_a); - nano::uint128_t bootstrap_threshold (); - std::size_t size (); - // clang-format off - class tag_arrival {}; - class tag_hash {}; - using ordered_gaps = boost::multi_index_container, - boost::multi_index::member>, - boost::multi_index::hashed_unique, - boost::multi_index::member>>>; - ordered_gaps blocks; - // clang-format on - std::size_t const max = 256; - nano::mutex mutex{ mutex_identifier (mutexes::gap_cache) }; - nano::node & node; -}; - -std::unique_ptr collect_container_info (gap_cache & gap_cache, std::string const & name); -} diff --git a/nano/node/gap_tracker.cpp b/nano/node/gap_tracker.cpp deleted file mode 100644 index 35c6e534a5..0000000000 --- a/nano/node/gap_tracker.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include - -nano::gap_tracker::gap_tracker (nano::gap_cache & gap_cache) : - gap_cache{ gap_cache } -{ -} - -void nano::gap_tracker::connect (nano::block_processor & block_processor) -{ - block_processor.processed.add ([this] (auto const & result, auto const & block) { - switch (result.code) - { - case nano::process_result::gap_previous: - case nano::process_result::gap_source: - observe (block); - break; - default: - break; - } - }); -} - -void nano::gap_tracker::observe (std::shared_ptr block) -{ - gap_cache.add (block->hash ()); -} diff --git a/nano/node/gap_tracker.hpp b/nano/node/gap_tracker.hpp deleted file mode 100644 index 6b8e54f264..0000000000 --- a/nano/node/gap_tracker.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -namespace nano -{ -class gap_cache; -class block_processor; -class block; - -// Observes the processed blocks and tracks them (gap_cache) if they are gap blocks. -class gap_tracker -{ -public: - gap_tracker (nano::gap_cache & gap_cache); - void connect (nano::block_processor & block_processor); - -private: - // Block_processor observer - void observe (std::shared_ptr block); - - nano::gap_cache & gap_cache; -}; -} diff --git a/nano/node/ipc/flatbuffers_util.cpp b/nano/node/ipc/flatbuffers_util.cpp index 8cf1fe5e40..f8265733fe 100644 --- a/nano/node/ipc/flatbuffers_util.cpp +++ b/nano/node/ipc/flatbuffers_util.cpp @@ -9,10 +9,10 @@ std::unique_ptr nano::ipc::flatbuffers_builder::from (nano block->account = block_a.account ().to_account (); block->hash = block_a.hash ().to_string (); block->previous = block_a.previous ().to_string (); - block->representative = block_a.representative ().to_account (); + block->representative = block_a.representative_field ().value ().to_account (); block->balance = block_a.balance ().to_string_dec (); - block->link = block_a.link ().to_string (); - block->link_as_account = block_a.link ().to_account (); + block->link = block_a.link_field ().value ().to_string (); + block->link_as_account = block_a.link_field ().value ().to_account (); block_a.signature.encode_hex (block->signature); block->work = nano::to_string_hex (block_a.work); @@ -20,7 +20,7 @@ std::unique_ptr nano::ipc::flatbuffers_builder::from (nano { block->subtype = nanoapi::BlockSubType::BlockSubType_send; } - else if (block_a.link ().is_zero ()) + else if (block_a.is_change ()) { block->subtype = nanoapi::BlockSubType::BlockSubType_change; } @@ -51,7 +51,7 @@ std::unique_ptr nano::ipc::flatbuffers_builder::from (na { auto block (std::make_unique ()); block->hash = block_a.hash ().to_string (); - block->source = block_a.source ().to_string (); + block->source = block_a.source_field ().value ().to_string (); block->previous = block_a.previous ().to_string (); block_a.signature.encode_hex (block->signature); block->work = nano::to_string_hex (block_a.work); @@ -62,9 +62,9 @@ std::unique_ptr nano::ipc::flatbuffers_builder::from (nano: { auto block (std::make_unique ()); block->hash = block_a.hash ().to_string (); - block->source = block_a.source ().to_string (); + block->source = block_a.source_field ().value ().to_string (); block->account = block_a.account ().to_account (); - block->representative = block_a.representative ().to_account (); + block->representative = block_a.representative_field ().value ().to_account (); block_a.signature.encode_hex (block->signature); block->work = nano::to_string_hex (block_a.work); return block; @@ -75,7 +75,7 @@ std::unique_ptr nano::ipc::flatbuffers_builder::from (nan auto block (std::make_unique ()); block->hash = block_a.hash ().to_string (); block->previous = block_a.previous ().to_string (); - block->representative = block_a.representative ().to_account (); + block->representative = block_a.representative_field ().value ().to_account (); block_a.signature.encode_hex (block->signature); block->work = nano::to_string_hex (block_a.work); return block; diff --git a/nano/node/ipc/ipc_broker.cpp b/nano/node/ipc/ipc_broker.cpp index 5176b3b131..15ba718cca 100644 --- a/nano/node/ipc/ipc_broker.cpp +++ b/nano/node/ipc/ipc_broker.cpp @@ -65,13 +65,13 @@ void nano::ipc::broker::start () } catch (nano::error const & err) { - this_l->node.logger.always_log ("IPC: could not broadcast message: ", err.get_message ()); + this_l->node.logger.error (nano::log::type::ipc, "Could not broadcast message: {}", err.get_message ()); } }); } template -void subscribe_or_unsubscribe (nano::logger_mt & logger, COLL & subscriber_collection, std::weak_ptr const & subscriber_a, TOPIC_TYPE topic_a) +void subscribe_or_unsubscribe (nano::logger & logger, COLL & subscriber_collection, std::weak_ptr const & subscriber_a, TOPIC_TYPE topic_a) { // Evict subscribers from dead sessions. Also remove current subscriber if unsubscribing. subscriber_collection.erase (std::remove_if (subscriber_collection.begin (), subscriber_collection.end (), @@ -85,7 +85,7 @@ void subscribe_or_unsubscribe (nano::logger_mt & logger, COLL & subscriber_colle remove = topic_a->unsubscribe && subscriber_l->get_id () == calling_subscriber_l->get_id (); if (remove) { - logger.always_log ("IPC: unsubscription from subscriber #", calling_subscriber_l->get_id ()); + logger.info (nano::log::type::ipc, "Subscriber ubsubscribed #{}", calling_subscriber_l->get_id ()); } } } diff --git a/nano/node/ipc/ipc_server.cpp b/nano/node/ipc/ipc_server.cpp index 9eaf1e7509..781f4051ac 100644 --- a/nano/node/ipc/ipc_server.cpp +++ b/nano/node/ipc/ipc_server.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -23,8 +22,6 @@ #include -using namespace boost::log; - namespace { /** @@ -39,10 +36,7 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f server (server_a), node (server_a.node), session_id (server_a.id_dispenser.fetch_add (1)), io_ctx (io_ctx_a), strand (io_ctx_a.get_executor ()), socket (io_ctx_a), config_transport (config_transport_a) { - if (node.config.logging.log_ipc ()) - { - node.logger.always_log ("IPC: created session with id: ", session_id.load ()); - } + node.logger.debug (nano::log::type::ipc, "Creating session with id: {}", session_id.load ()); } ~session () @@ -234,10 +228,7 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f this_l->timer_cancel (); if (ec == boost::asio::error::broken_pipe || ec == boost::asio::error::connection_aborted || ec == boost::asio::error::connection_reset || ec == boost::asio::error::connection_refused) { - if (this_l->node.config.logging.log_ipc ()) - { - this_l->node.logger.always_log (boost::str (boost::format ("IPC: error reading %1% ") % ec.message ())); - } + this_l->node.logger.error (nano::log::type::ipc, "Error reading: ", ec.message ()); } else if (bytes_transferred_a > 0) { @@ -260,10 +251,11 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f auto buffer (std::make_shared> ()); buffer->insert (buffer->end (), reinterpret_cast (&big), reinterpret_cast (&big) + sizeof (std::uint32_t)); buffer->insert (buffer->end (), body.begin (), body.end ()); - if (this_l->node.config.logging.log_ipc ()) - { - this_l->node.logger.always_log (boost::str (boost::format ("IPC/RPC request %1% completed in: %2% %3%") % request_id_l % this_l->session_timer.stop ().count () % this_l->session_timer.unit ())); - } + + this_l->node.logger.debug (nano::log::type::ipc, "IPC/RPC request {} completed in: {} {}", + request_id_l, + this_l->session_timer.stop ().count (), + this_l->session_timer.unit ()); this_l->timer_start (std::chrono::seconds (this_l->config_transport.io_timeout)); this_l->queued_write (boost::asio::buffer (buffer->data (), buffer->size ()), [this_l, buffer] (boost::system::error_code const & error_a, std::size_t size_a) { @@ -272,9 +264,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f { this_l->read_next_request (); } - else if (this_l->node.config.logging.log_ipc ()) + else { - this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ()); + this_l->node.logger.error (nano::log::type::ipc, "Write failed: ", error_a.message ()); } }); @@ -307,10 +299,7 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f this_l->active_encoding = static_cast (encoding); if (this_l->buffer[nano::ipc::preamble_offset::lead] != 'N' || this_l->buffer[nano::ipc::preamble_offset::reserved_1] != 0 || this_l->buffer[nano::ipc::preamble_offset::reserved_2] != 0) { - if (this_l->node.config.logging.log_ipc ()) - { - this_l->node.logger.always_log ("IPC: Invalid preamble"); - } + this_l->node.logger.error (nano::log::type::ipc, "Invalid preamble"); } else if (encoding == static_cast (nano::ipc::payload_encoding::json_v1) || encoding == static_cast (nano::ipc::payload_encoding::json_v1_unsafe)) { @@ -344,10 +333,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f if (encoding == static_cast (nano::ipc::payload_encoding::flatbuffers_json)) { this_l->flatbuffers_handler->process_json (this_l->buffer.data (), this_l->buffer_size, [this_l] (std::shared_ptr const & body) { - if (this_l->node.config.logging.log_ipc ()) - { - this_l->node.logger.always_log (boost::str (boost::format ("IPC/Flatbuffer request completed in: %1% %2%") % this_l->session_timer.stop ().count () % this_l->session_timer.unit ())); - } + this_l->node.logger.debug (nano::log::type::ipc, "IPC/Flatbuffer request completed in: {} {}", + this_l->session_timer.stop ().count (), + this_l->session_timer.unit ()); auto big_endian_length = std::make_shared (boost::endian::native_to_big (static_cast (body->size ()))); boost::array buffers = { @@ -360,9 +348,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f { this_l->read_next_request (); } - else if (this_l->node.config.logging.log_ipc ()) + else { - this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ()); + this_l->node.logger.error (nano::log::type::ipc, "Write failed: {}", error_a.message ()); } }); }); @@ -370,10 +358,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f else { this_l->flatbuffers_handler->process (this_l->buffer.data (), this_l->buffer_size, [this_l] (std::shared_ptr const & fbb) { - if (this_l->node.config.logging.log_ipc ()) - { - this_l->node.logger.always_log (boost::str (boost::format ("IPC/Flatbuffer request completed in: %1% %2%") % this_l->session_timer.stop ().count () % this_l->session_timer.unit ())); - } + this_l->node.logger.debug (nano::log::type::ipc, "IPC/Flatbuffer request completed in: {} {}", + this_l->session_timer.stop ().count (), + this_l->session_timer.unit ()); auto big_endian_length = std::make_shared (boost::endian::native_to_big (static_cast (fbb->GetSize ()))); boost::array buffers = { @@ -386,9 +373,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f { this_l->read_next_request (); } - else if (this_l->node.config.logging.log_ipc ()) + else { - this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ()); + this_l->node.logger.error (nano::log::type::ipc, "Write failed: {}", error_a.message ()); } }); }); @@ -396,9 +383,9 @@ class session final : public nano::ipc::socket_base, public std::enable_shared_f }); }); } - else if (this_l->node.config.logging.log_ipc ()) + else { - this_l->node.logger.always_log ("IPC: Unsupported payload encoding"); + this_l->node.logger.error (nano::log::type::ipc, "Unsupported payload encoding"); } }); } @@ -523,7 +510,7 @@ class socket_transport : public nano::ipc::transport } else { - node->logger.always_log ("IPC: acceptor error: ", ec.message ()); + node->logger.error (nano::log::type::ipc, "Acceptor error: ", ec.message ()); } if (ec != boost::asio::error::operation_aborted && acceptor->is_open ()) @@ -532,7 +519,7 @@ class socket_transport : public nano::ipc::transport } else { - node->logger.always_log ("IPC: shutting down"); + node->logger.info (nano::log::type::ipc, "Shutting down"); } }); } @@ -614,7 +601,7 @@ nano::ipc::ipc_server::ipc_server (nano::node & node_a, nano::node_rpc_config co } #ifndef _WIN32 // Hook up config reloading through the HUP signal - auto signals (std::make_shared (node.io_ctx, SIGHUP)); + signals = std::make_shared (node.io_ctx, SIGHUP); await_hup_signal (signals, *this); #endif if (node_a.config.ipc_config.transport_domain.enabled) @@ -625,7 +612,7 @@ nano::ipc::ipc_server::ipc_server (nano::node & node_a, nano::node_rpc_config co boost::asio::local::stream_protocol::endpoint ep{ node_a.config.ipc_config.transport_domain.path }; transports.push_back (std::make_shared (*this, ep, node_a.config.ipc_config.transport_domain, threads)); #else - node.logger.always_log ("IPC: Domain sockets are not supported on this platform"); + node.logger.error (nano::log::type::ipc_server, "Domain sockets are not supported on this platform"); #endif } @@ -635,7 +622,7 @@ nano::ipc::ipc_server::ipc_server (nano::node & node_a, nano::node_rpc_config co transports.push_back (std::make_shared (*this, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v6 (), node_a.config.ipc_config.transport_tcp.port), node_a.config.ipc_config.transport_tcp, threads)); } - node.logger.always_log ("IPC: server started"); + node.logger.debug (nano::log::type::ipc_server, "Server started"); if (!transports.empty ()) { @@ -644,13 +631,13 @@ nano::ipc::ipc_server::ipc_server (nano::node & node_a, nano::node_rpc_config co } catch (std::runtime_error const & ex) { - node.logger.always_log ("IPC: ", ex.what ()); + node.logger.error (nano::log::type::ipc_server, "Error: {}", ex.what ()); } } nano::ipc::ipc_server::~ipc_server () { - node.logger.always_log ("IPC: server stopped"); + node.logger.debug (nano::log::type::ipc_server, "Server stopped"); } void nano::ipc::ipc_server::stop () @@ -659,6 +646,10 @@ void nano::ipc::ipc_server::stop () { transport->stop (); } + if (signals) + { + signals->cancel (); + } } std::optional nano::ipc::ipc_server::listening_tcp_port () const @@ -690,9 +681,7 @@ nano::error nano::ipc::ipc_server::reload_access_config () nano::error access_config_error (nano::ipc::read_access_config_toml (node.application_path, access)); if (access_config_error) { - auto error (boost::str (boost::format ("IPC: invalid access configuration file: %1%") % access_config_error.get_message ())); - std::cerr << error << std::endl; - node.logger.always_log (error); + node.logger.error (nano::log::type::ipc_server, "Invalid access configuration file: {}", access_config_error.get_message ()); } return access_config_error; } diff --git a/nano/node/ipc/ipc_server.hpp b/nano/node/ipc/ipc_server.hpp index a9f175dbbc..378d78eb32 100644 --- a/nano/node/ipc/ipc_server.hpp +++ b/nano/node/ipc/ipc_server.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include #include @@ -41,6 +43,7 @@ namespace ipc nano::ipc::access access; std::unique_ptr file_remover; std::vector> transports; + std::shared_ptr signals; }; } } diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 3e6683da74..27e7c92f12 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include @@ -397,12 +399,12 @@ uint64_t nano::json_handler::difficulty_ledger (nano::block const & block_a) auto previous (block_a.previous ()); if (!previous.is_zero ()) { - block_previous = node.store.block.get (transaction, previous); + block_previous = node.ledger.block (transaction, previous); } // Send check if (block_previous != nullptr) { - details.is_send = node.ledger.balance (transaction, previous) > block_a.balance ().number (); + details.is_send = node.ledger.balance (transaction, previous) > block_a.balance_field ().value ().number (); details_found = true; } // Epoch check @@ -410,11 +412,12 @@ uint64_t nano::json_handler::difficulty_ledger (nano::block const & block_a) { details.epoch = block_previous->sideband ().details.epoch; } - auto link (block_a.link ()); - if (!link.is_zero () && !details.is_send) + auto link = block_a.link_field (); + if (link && !link.value ().is_zero () && !details.is_send) { - auto block_link (node.store.block.get (transaction, link.as_block_hash ())); - if (block_link != nullptr && node.store.pending.exists (transaction, nano::pending_key (block_a.account (), link.as_block_hash ()))) + auto block_link = node.ledger.block (transaction, link.value ().as_block_hash ()); + auto account = block_a.account_field ().value (); // Link is non-zero therefore it's a state block and has an account field; + if (block_link != nullptr && node.store.pending.exists (transaction, nano::pending_key (account, link.value ().as_block_hash ()))) { details.epoch = std::max (details.epoch, block_link->sideband ().details.epoch); details.is_receive = true; @@ -641,7 +644,7 @@ void nano::json_handler::account_info () { if (info.block_count != confirmation_height_info.height) { - confirmed_balance_l = node.ledger.balance (transaction, confirmation_height_info.frontier); + confirmed_balance_l = node.ledger.balance (transaction, confirmation_height_info.frontier).value_or (0); } else { @@ -672,7 +675,7 @@ void nano::json_handler::account_info () std::shared_ptr confirmed_frontier_block; if (include_confirmed && confirmation_height_info.height > 0) { - confirmed_frontier_block = node.store.block.get (transaction, confirmation_height_info.frontier); + confirmed_frontier_block = node.ledger.block (transaction, confirmation_height_info.frontier); } if (representative) @@ -683,10 +686,10 @@ void nano::json_handler::account_info () nano::account confirmed_representative{}; if (confirmed_frontier_block) { - confirmed_representative = confirmed_frontier_block->representative (); + confirmed_representative = confirmed_frontier_block->representative_field ().value_or (0); if (confirmed_representative.is_zero ()) { - confirmed_representative = node.store.block.get (transaction, node.ledger.representative (transaction, confirmation_height_info.frontier))->representative (); + confirmed_representative = node.ledger.block (transaction, node.ledger.representative (transaction, confirmation_height_info.frontier))->representative_field ().value (); } } @@ -1145,19 +1148,18 @@ void nano::json_handler::block_info () if (!ec) { auto transaction (node.store.tx_begin_read ()); - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); if (block != nullptr) { - nano::account account (block->account ().is_zero () ? block->sideband ().account : block->account ()); + auto account = block->account (); response_l.put ("block_account", account.to_account ()); - bool error_or_pruned (false); - auto amount (node.ledger.amount_safe (transaction, hash, error_or_pruned)); - if (!error_or_pruned) + auto amount = node.ledger.amount (transaction, hash); + if (amount) { - response_l.put ("amount", amount.convert_to ()); + response_l.put ("amount", amount.value ().convert_to ()); } - auto balance (node.ledger.balance (transaction, hash)); - response_l.put ("balance", balance.convert_to ()); + auto balance = block->balance (); + response_l.put ("balance", balance.number ().convert_to ()); response_l.put ("height", std::to_string (block->sideband ().height)); response_l.put ("local_timestamp", std::to_string (block->sideband ().timestamp)); response_l.put ("successor", block->sideband ().successor.to_string ()); @@ -1197,7 +1199,7 @@ void nano::json_handler::block_confirm () if (!ec) { auto transaction (node.store.tx_begin_read ()); - auto block_l (node.store.block.get (transaction, hash)); + auto block_l = node.ledger.block (transaction, hash); if (block_l != nullptr) { if (!node.ledger.block_confirmed (transaction, hash)) @@ -1214,21 +1216,19 @@ void nano::json_handler::block_confirm () nano::election_status status{ block_l, 0, 0, std::chrono::duration_cast (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values::zero (), 0, 1, 0, nano::election_status_type::active_confirmation_height }; node.active.recently_cemented.put (status); // Trigger callback for confirmed block - node.block_arrival.add (hash); - auto account (node.ledger.account (transaction, hash)); - bool error_or_pruned (false); - auto amount (node.ledger.amount_safe (transaction, hash, error_or_pruned)); + auto account = block_l->account (); + auto amount = node.ledger.amount (transaction, hash); bool is_state_send (false); bool is_state_epoch (false); - if (!error_or_pruned) + if (amount) { if (auto state = dynamic_cast (block_l.get ())) { - is_state_send = node.ledger.is_send (transaction, *state); - is_state_epoch = amount == 0 && node.ledger.is_epoch_link (state->link ()); + is_state_send = state->is_send (); + is_state_epoch = amount.value () == 0 && node.ledger.is_epoch_link (state->link_field ().value ()); } } - node.observers.blocks.notify (status, {}, account, amount, is_state_send, is_state_epoch); + node.observers.blocks.notify (status, {}, account, amount ? amount.value () : 0, is_state_send, is_state_epoch); } response_l.put ("started", "1"); } @@ -1253,7 +1253,7 @@ void nano::json_handler::blocks () nano::block_hash hash; if (!hash.decode_hex (hash_text)) { - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); if (block != nullptr) { if (json_block_l) @@ -1304,20 +1304,19 @@ void nano::json_handler::blocks_info () nano::block_hash hash; if (!hash.decode_hex (hash_text)) { - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); if (block != nullptr) { boost::property_tree::ptree entry; - nano::account account (block->account ().is_zero () ? block->sideband ().account : block->account ()); + auto account = block->account (); entry.put ("block_account", account.to_account ()); - bool error_or_pruned (false); - auto amount (node.ledger.amount_safe (transaction, hash, error_or_pruned)); - if (!error_or_pruned) + auto amount = node.ledger.amount (transaction, hash); + if (amount) { - entry.put ("amount", amount.convert_to ()); + entry.put ("amount", amount.value ().convert_to ()); } - auto balance (node.ledger.balance (transaction, hash)); - entry.put ("balance", balance.convert_to ()); + auto balance = block->balance (); + entry.put ("balance", balance.number ().convert_to ()); entry.put ("height", std::to_string (block->sideband ().height)); entry.put ("local_timestamp", std::to_string (block->sideband ().timestamp)); entry.put ("successor", block->sideband ().successor.to_string ()); @@ -1343,8 +1342,7 @@ void nano::json_handler::blocks_info () } if (receivable || receive_hash) { - auto destination (node.ledger.block_destination (transaction, *block)); - if (destination.is_zero ()) + if (!block->is_send ()) { if (receivable) { @@ -1356,7 +1354,7 @@ void nano::json_handler::blocks_info () entry.put ("receive_hash", nano::block_hash (0).to_string ()); } } - else if (node.store.pending.exists (transaction, nano::pending_key (destination, hash))) + else if (node.store.pending.exists (transaction, nano::pending_key (block->destination (), hash))) { if (receivable) { @@ -1377,7 +1375,7 @@ void nano::json_handler::blocks_info () } if (receive_hash) { - std::shared_ptr receive_block = node.ledger.find_receive_block_by_send_hash (transaction, destination, hash); + std::shared_ptr receive_block = node.ledger.find_receive_block_by_send_hash (transaction, block->destination (), hash); std::string receive_hash = receive_block ? receive_block->hash ().to_string () : nano::block_hash (0).to_string (); entry.put ("receive_hash", receive_hash); } @@ -1385,16 +1383,15 @@ void nano::json_handler::blocks_info () } if (source) { - nano::block_hash source_hash (node.ledger.block_source (transaction, *block)); - auto block_a (node.store.block.get (transaction, source_hash)); - if (block_a != nullptr) + if (!block->is_receive () || !node.ledger.block_exists (transaction, block->source ())) { - auto source_account (node.ledger.account (transaction, source_hash)); - entry.put ("source_account", source_account.to_account ()); + entry.put ("source_account", "0"); } else { - entry.put ("source_account", "0"); + auto block_a = node.ledger.block (transaction, block->source ()); + release_assert (block_a); + entry.put ("source_account", block_a->account ().to_account ()); } } blocks.push_back (std::make_pair (hash_text, entry)); @@ -1433,10 +1430,10 @@ void nano::json_handler::block_account () if (!ec) { auto transaction (node.store.tx_begin_read ()); - if (node.store.block.exists (transaction, hash)) + auto block = node.ledger.block (transaction, hash); + if (block) { - auto account (node.ledger.account (transaction, hash)); - response_l.put ("account", account.to_account ()); + response_l.put ("account", block->account ().to_account ()); } else { @@ -1616,10 +1613,10 @@ void nano::json_handler::block_create () // Wrapper from argument to lambda capture, to extend the block's scope auto get_callback_l = [rpc_l, block_response_put_l] (std::shared_ptr const & block_a) { // Callback upon work generation success or failure - return [block_a, rpc_l, block_response_put_l] (boost::optional const & work_a) { + return [block_a, rpc_l, block_response_put_l] (std::optional const & work_a) { if (block_a != nullptr) { - if (work_a.is_initialized ()) + if (work_a.has_value ()) { block_a->block_work_set (*work_a); block_response_put_l (*block_a); @@ -1653,7 +1650,7 @@ void nano::json_handler::block_create () else if (previous_text.is_initialized () && balance_text.is_initialized () && type == "send") { auto transaction (node.store.tx_begin_read ()); - if (node.store.block.exists (transaction, previous) && node.ledger.balance (transaction, previous) != balance.number ()) + if (node.ledger.block_exists (transaction, previous) && node.ledger.balance (transaction, previous) != balance.number ()) { ec = nano::error_rpc::block_create_balance_mismatch; } @@ -1946,7 +1943,7 @@ void nano::json_handler::chain (bool successors) auto transaction (node.store.tx_begin_read ()); while (!hash.is_zero () && blocks.size () < count) { - auto block_l (node.store.block.get (transaction, hash)); + auto block_l = node.ledger.block (transaction, hash); if (block_l != nullptr) { if (offset > 0) @@ -2396,11 +2393,10 @@ class history_visitor : public nano::block_visitor tree.put ("type", "send"); auto account (block_a.hashables.destination.to_account ()); tree.put ("account", account); - bool error_or_pruned (false); - auto amount (handler.node.ledger.amount_safe (transaction, hash, error_or_pruned).convert_to ()); - if (!error_or_pruned) + auto amount = handler.node.ledger.amount (transaction, hash); + if (amount) { - tree.put ("amount", amount); + tree.put ("amount", amount.value ().convert_to ()); } if (raw) { @@ -2412,16 +2408,15 @@ class history_visitor : public nano::block_visitor void receive_block (nano::receive_block const & block_a) { tree.put ("type", "receive"); - bool error_or_pruned (false); - auto amount (handler.node.ledger.amount_safe (transaction, hash, error_or_pruned).convert_to ()); - if (!error_or_pruned) + auto amount = handler.node.ledger.amount (transaction, hash); + if (amount) { - auto source_account (handler.node.ledger.account_safe (transaction, block_a.hashables.source, error_or_pruned)); - if (!error_or_pruned) + auto source_account = handler.node.ledger.account (transaction, block_a.hashables.source); + if (source_account) { - tree.put ("account", source_account.to_account ()); + tree.put ("account", source_account.value ().to_account ()); } - tree.put ("amount", amount); + tree.put ("amount", amount.value ().convert_to ()); } if (raw) { @@ -2446,15 +2441,15 @@ class history_visitor : public nano::block_visitor if (block_a.hashables.source != handler.node.ledger.constants.genesis->account ()) { bool error_or_pruned (false); - auto amount (handler.node.ledger.amount_safe (transaction, hash, error_or_pruned).convert_to ()); - if (!error_or_pruned) + auto amount = handler.node.ledger.amount (transaction, hash); + if (amount) { - auto source_account (handler.node.ledger.account_safe (transaction, block_a.hashables.source, error_or_pruned)); - if (!error_or_pruned) + auto source_account = handler.node.ledger.account (transaction, block_a.hashables.source); + if (source_account) { - tree.put ("account", source_account.to_account ()); + tree.put ("account", source_account.value ().to_account ()); } - tree.put ("amount", amount); + tree.put ("amount", amount.value ().convert_to ()); } } else @@ -2483,9 +2478,8 @@ class history_visitor : public nano::block_visitor tree.put ("previous", block_a.hashables.previous.to_string ()); } auto balance (block_a.hashables.balance.number ()); - bool error_or_pruned (false); - auto previous_balance (handler.node.ledger.balance_safe (transaction, block_a.hashables.previous, error_or_pruned)); - if (error_or_pruned) + auto previous_balance = handler.node.ledger.balance (transaction, block_a.hashables.previous); + if (!previous_balance) { if (raw) { @@ -2496,7 +2490,7 @@ class history_visitor : public nano::block_visitor tree.put ("type", "unknown"); } } - else if (balance < previous_balance) + else if (balance < previous_balance.value ()) { if (should_ignore_account (block_a.hashables.link.as_account ())) { @@ -2512,7 +2506,7 @@ class history_visitor : public nano::block_visitor tree.put ("type", "send"); } tree.put ("account", block_a.hashables.link.to_account ()); - tree.put ("amount", (previous_balance - balance).convert_to ()); + tree.put ("amount", (previous_balance.value () - balance).convert_to ()); } else { @@ -2528,13 +2522,13 @@ class history_visitor : public nano::block_visitor if (raw && accounts_filter.empty ()) { tree.put ("subtype", "epoch"); - tree.put ("account", handler.node.ledger.epoch_signer (block_a.link ()).to_account ()); + tree.put ("account", handler.node.ledger.epoch_signer (block_a.link_field ().value ()).to_account ()); } } else { - auto source_account (handler.node.ledger.account_safe (transaction, block_a.hashables.link.as_block_hash (), error_or_pruned)); - if (!error_or_pruned && should_ignore_account (source_account)) + auto source_account = handler.node.ledger.account (transaction, block_a.hashables.link.as_block_hash ()); + if (source_account && should_ignore_account (source_account.value ())) { tree.clear (); return; @@ -2547,11 +2541,11 @@ class history_visitor : public nano::block_visitor { tree.put ("type", "receive"); } - if (!error_or_pruned) + if (source_account) { - tree.put ("account", source_account.to_account ()); + tree.put ("account", source_account.value ().to_account ()); } - tree.put ("amount", (balance - previous_balance).convert_to ()); + tree.put ("amount", (balance - previous_balance.value ()).convert_to ()); } } } @@ -2606,9 +2600,9 @@ void nano::json_handler::account_history () { if (!hash.decode_hex (*head_str)) { - if (node.store.block.exists (transaction, hash)) + if (node.ledger.block_exists (transaction, hash)) { - account = node.ledger.account (transaction, hash); + account = node.ledger.account (transaction, hash).value (); } else { @@ -2644,7 +2638,7 @@ void nano::json_handler::account_history () boost::property_tree::ptree history; bool output_raw (request.get_optional ("raw") == true); response_l.put ("account", account.to_account ()); - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); while (block != nullptr && count > 0) { if (offset > 0) @@ -2672,7 +2666,7 @@ void nano::json_handler::account_history () } } hash = reverse ? node.store.block.successor (transaction, hash) : block->previous (); - block = node.store.block.get (transaction, hash); + block = node.ledger.block (transaction, hash); } response_l.add_child ("history", history); if (!hash.is_zero ()) @@ -2923,7 +2917,6 @@ void nano::json_handler::node_id () { if (!ec) { - response_l.put ("private", node.node_id.prv.to_string ()); response_l.put ("public", node.node_id.pub.to_string ()); response_l.put ("as_account", node.node_id.pub.to_account ()); response_l.put ("node_id", node.node_id.pub.to_node_id ()); @@ -2955,7 +2948,7 @@ void nano::json_handler::password_change () rpc_l->response_l.put ("changed", error ? "0" : "1"); if (!error) { - rpc_l->node.logger.try_log ("Wallet password changed"); + rpc_l->node.logger.warn (nano::log::type::rpc, "Wallet password changed"); } } } @@ -3165,14 +3158,13 @@ void nano::json_handler::receivable_exists () if (!ec) { auto transaction (node.store.tx_begin_read ()); - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); if (block != nullptr) { auto exists (false); - auto destination (node.ledger.block_destination (transaction, *block)); - if (!destination.is_zero ()) + if (block->is_send ()) { - exists = node.store.pending.exists (transaction, nano::pending_key (destination, hash)); + exists = node.store.pending.exists (transaction, nano::pending_key (block->destination (), hash)); } exists = exists && (block_confirmed (node, transaction, block->hash (), include_active, include_only_confirmed)); response_l.put ("exists", exists ? "1" : "0"); @@ -3199,7 +3191,7 @@ void nano::json_handler::process () { std::shared_ptr block_state (std::static_pointer_cast (block)); auto transaction (rpc_l->node.store.tx_begin_read ()); - if (!block_state->hashables.previous.is_zero () && !rpc_l->node.store.block.exists (transaction, block_state->hashables.previous)) + if (!block_state->hashables.previous.is_zero () && !rpc_l->node.ledger.block_exists (transaction, block_state->hashables.previous)) { rpc_l->ec = nano::error_process::gap_previous; } @@ -3272,60 +3264,60 @@ void nano::json_handler::process () else { auto const & result = result_maybe.value (); - switch (result.code) + switch (result) { - case nano::process_result::progress: + case nano::block_status::progress: { rpc_l->response_l.put ("hash", block->hash ().to_string ()); break; } - case nano::process_result::gap_previous: + case nano::block_status::gap_previous: { rpc_l->ec = nano::error_process::gap_previous; break; } - case nano::process_result::gap_source: + case nano::block_status::gap_source: { rpc_l->ec = nano::error_process::gap_source; break; } - case nano::process_result::old: + case nano::block_status::old: { rpc_l->ec = nano::error_process::old; break; } - case nano::process_result::bad_signature: + case nano::block_status::bad_signature: { rpc_l->ec = nano::error_process::bad_signature; break; } - case nano::process_result::negative_spend: + case nano::block_status::negative_spend: { // TODO once we get RPC versioning, this should be changed to "negative spend" rpc_l->ec = nano::error_process::negative_spend; break; } - case nano::process_result::balance_mismatch: + case nano::block_status::balance_mismatch: { rpc_l->ec = nano::error_process::balance_mismatch; break; } - case nano::process_result::unreceivable: + case nano::block_status::unreceivable: { rpc_l->ec = nano::error_process::unreceivable; break; } - case nano::process_result::block_position: + case nano::block_status::block_position: { rpc_l->ec = nano::error_process::block_position; break; } - case nano::process_result::gap_epoch_open_pending: + case nano::block_status::gap_epoch_open_pending: { rpc_l->ec = nano::error_process::gap_epoch_open_pending; break; } - case nano::process_result::fork: + case nano::block_status::fork: { bool const force = rpc_l->request.get ("force", false); if (force) @@ -3340,12 +3332,12 @@ void nano::json_handler::process () } break; } - case nano::process_result::insufficient_work: + case nano::block_status::insufficient_work: { rpc_l->ec = nano::error_process::insufficient_work; break; } - case nano::process_result::opened_burn_account: + case nano::block_status::opened_burn_account: rpc_l->ec = nano::error_process::opened_burn_account; break; default: @@ -3639,28 +3631,28 @@ void nano::json_handler::republish () { boost::property_tree::ptree blocks; auto transaction (node.store.tx_begin_read ()); - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); if (block != nullptr) { std::deque> republish_bundle; for (auto i (0); !hash.is_zero () && i < count; ++i) { - block = node.store.block.get (transaction, hash); + block = node.ledger.block (transaction, hash); if (sources != 0) // Republish source chain { - nano::block_hash source (node.ledger.block_source (transaction, *block)); - auto block_a (node.store.block.get (transaction, source)); + nano::block_hash source = block->source_field ().value_or (block->link_field ().value_or (0).as_block_hash ()); + auto block_a = node.ledger.block (transaction, source); std::vector hashes; while (block_a != nullptr && hashes.size () < sources) { hashes.push_back (source); source = block_a->previous (); - block_a = node.store.block.get (transaction, source); + block_a = node.ledger.block (transaction, source); } std::reverse (hashes.begin (), hashes.end ()); for (auto & hash_l : hashes) { - block_a = node.store.block.get (transaction, hash_l); + block_a = node.ledger.block (transaction, hash_l); republish_bundle.push_back (std::move (block_a)); boost::property_tree::ptree entry_l; entry_l.put ("", hash_l.to_string ()); @@ -3673,22 +3665,22 @@ void nano::json_handler::republish () blocks.push_back (std::make_pair ("", entry)); if (destinations != 0) // Republish destination chain { - auto block_b (node.store.block.get (transaction, hash)); - auto destination (node.ledger.block_destination (transaction, *block_b)); + auto block_b = node.ledger.block (transaction, hash); + auto destination = block_b->destination (); if (!destination.is_zero ()) { if (!node.store.pending.exists (transaction, nano::pending_key (destination, hash))) { nano::block_hash previous (node.ledger.latest (transaction, destination)); - auto block_d (node.store.block.get (transaction, previous)); + auto block_d = node.ledger.block (transaction, previous); nano::block_hash source; std::vector hashes; while (block_d != nullptr && hash != source) { hashes.push_back (previous); - source = node.ledger.block_source (transaction, *block_d); + source = block_d->source_field ().value_or (block_d->is_send () ? 0 : block_d->link_field ().value_or (0).as_block_hash ()); previous = block_d->previous (); - block_d = node.store.block.get (transaction, previous); + block_d = node.ledger.block (transaction, previous); } std::reverse (hashes.begin (), hashes.end ()); if (hashes.size () > destinations) @@ -3697,7 +3689,7 @@ void nano::json_handler::republish () } for (auto & hash_l : hashes) { - block_d = node.store.block.get (transaction, hash_l); + block_d = node.ledger.block (transaction, hash_l); republish_bundle.push_back (std::move (block_d)); boost::property_tree::ptree entry_l; entry_l.put ("", hash_l.to_string ()); @@ -4659,7 +4651,7 @@ void nano::json_handler::wallet_history () auto hash (info->head); while (timestamp >= modified_since && !hash.is_zero ()) { - auto block (node.store.block.get (block_transaction, hash)); + auto block = node.ledger.block (block_transaction, hash); timestamp = block->sideband ().timestamp; if (block != nullptr && timestamp >= modified_since) { @@ -4773,7 +4765,8 @@ void nano::json_handler::wallet_lock () empty.clear (); wallet->store.password.value_set (empty); response_l.put ("locked", "1"); - node.logger.try_log ("Wallet locked"); + + node.logger.warn (nano::log::type::rpc, "Wallet locked"); } response_errors (); } @@ -4932,7 +4925,7 @@ void nano::json_handler::wallet_republish () while (!latest.is_zero () && hashes.size () < count) { hashes.push_back (latest); - block = node.store.block.get (block_transaction, latest); + block = node.ledger.block (block_transaction, latest); if (block != nullptr) { latest = block->previous (); @@ -4945,7 +4938,7 @@ void nano::json_handler::wallet_republish () std::reverse (hashes.begin (), hashes.end ()); for (auto & hash : hashes) { - block = node.store.block.get (block_transaction, hash); + block = node.ledger.block (block_transaction, hash); republish_bundle.push_back (std::move (block)); boost::property_tree::ptree entry; entry.put ("", hash.to_string ()); @@ -5000,7 +4993,7 @@ void nano::json_handler::wallet_work_get () void nano::json_handler::work_generate () { - boost::optional account; + std::optional account; auto account_opt (request.get_optional ("account")); // Default to work_1 if not specified auto work_version (work_version_optional_impl (nano::work_version::work_1)); @@ -5052,7 +5045,7 @@ void nano::json_handler::work_generate () { auto use_peers (request.get ("use_peers", false)); auto rpc_l (shared_from_this ()); - auto callback = [rpc_l, hash, work_version, this] (boost::optional const & work_a) { + auto callback = [rpc_l, hash, work_version, this] (std::optional const & work_a) { if (work_a) { boost::property_tree::ptree response_l; @@ -5093,9 +5086,9 @@ void nano::json_handler::work_generate () { // Fetch account from block if not given auto transaction_l (node.store.tx_begin_read ()); - if (node.store.block.exists (transaction_l, hash)) + if (node.ledger.block_exists (transaction_l, hash)) { - account = node.ledger.account (transaction_l, hash); + account = node.ledger.account (transaction_l, hash).value (); } } auto secondary_work_peers_l (request.get ("secondary_work_peers", false)); @@ -5463,7 +5456,7 @@ bool block_confirmed (nano::node & node, nano::store::transaction & transaction, // This just checks it's not currently undergoing an active transaction else if (!include_only_confirmed) { - auto block (node.store.block.get (transaction, hash)); + auto block = node.ledger.block (transaction, hash); is_confirmed = (block != nullptr && !node.active.active (*block)); } diff --git a/nano/node/local_block_broadcaster.cpp b/nano/node/local_block_broadcaster.cpp new file mode 100644 index 0000000000..59c0e4dffd --- /dev/null +++ b/nano/node/local_block_broadcaster.cpp @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include + +nano::local_block_broadcaster::local_block_broadcaster (nano::node & node_a, nano::block_processor & block_processor_a, nano::network & network_a, nano::stats & stats_a, bool enabled_a) : + node{ node_a }, + block_processor{ block_processor_a }, + network{ network_a }, + stats{ stats_a }, + enabled{ enabled_a } +{ + if (!enabled) + { + return; + } + + block_processor.batch_processed.add ([this] (auto const & batch) { + bool should_notify = false; + for (auto const & [result, context] : batch) + { + // Only rebroadcast local blocks that were successfully processed (no forks or gaps) + if (result == nano::block_status::progress && context.source == nano::block_source::local) + { + nano::lock_guard guard{ mutex }; + local_blocks.emplace_back (local_entry{ context.block, std::chrono::steady_clock::now () }); + stats.inc (nano::stat::type::local_block_broadcaster, nano::stat::detail::insert); + should_notify = true; + } + } + if (should_notify) + { + condition.notify_all (); + } + }); + + block_processor.rolled_back.add ([this] (auto const & block) { + nano::lock_guard guard{ mutex }; + auto erased = local_blocks.get ().erase (block->hash ()); + stats.add (nano::stat::type::local_block_broadcaster, nano::stat::detail::rollback, nano::stat::dir::in, erased); + }); +} + +nano::local_block_broadcaster::~local_block_broadcaster () +{ + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); +} + +void nano::local_block_broadcaster::start () +{ + if (!enabled) + { + return; + } + + debug_assert (!thread.joinable ()); + + thread = std::thread{ [this] () { + nano::thread_role::set (nano::thread_role::name::local_block_broadcasting); + run (); + } }; +} + +void nano::local_block_broadcaster::stop () +{ + { + nano::lock_guard lock{ mutex }; + stopped = true; + } + condition.notify_all (); + nano::join_or_pass (thread); +} + +void nano::local_block_broadcaster::run () +{ + nano::unique_lock lock{ mutex }; + while (!stopped) + { + stats.inc (nano::stat::type::local_block_broadcaster, nano::stat::detail::loop); + + condition.wait_for (lock, check_interval); + debug_assert ((std::this_thread::yield (), true)); // Introduce some random delay in debug builds + + if (!stopped) + { + cleanup (); + run_broadcasts (lock); + debug_assert (lock.owns_lock ()); + } + } +} + +void nano::local_block_broadcaster::run_broadcasts (nano::unique_lock & lock) +{ + debug_assert (lock.owns_lock ()); + + std::vector> to_broadcast; + + auto const now = std::chrono::steady_clock::now (); + for (auto & entry : local_blocks) + { + if (elapsed (entry.last_broadcast, broadcast_interval, now)) + { + entry.last_broadcast = now; + to_broadcast.push_back (entry.block); + } + } + + lock.unlock (); + + for (auto const & block : to_broadcast) + { + while (!limiter.should_pass (1)) + { + std::this_thread::sleep_for (std::chrono::milliseconds{ 100 }); + if (stopped) + { + return; + } + } + + stats.inc (nano::stat::type::local_block_broadcaster, nano::stat::detail::broadcast, nano::stat::dir::out); + + network.flood_block_initial (block); + } + + lock.lock (); +} + +void nano::local_block_broadcaster::cleanup () +{ + debug_assert (!mutex.try_lock ()); + + // Erase oldest blocks if the queue gets too big + while (local_blocks.size () > max_size) + { + stats.inc (nano::stat::type::local_block_broadcaster, nano::stat::detail::erase_oldest); + local_blocks.pop_front (); + } + + // TODO: Mutex is held during IO, but it should be fine since it's not performance critical + auto transaction = node.store.tx_begin_read (); + erase_if (local_blocks, [this, &transaction] (auto const & entry) { + transaction.refresh_if_needed (); + + if (entry.last_broadcast == std::chrono::steady_clock::time_point{}) + { + // This block has never been broadcasted, keep it so it's broadcasted at least once + return false; + } + if (node.block_confirmed_or_being_confirmed (transaction, entry.block->hash ())) + { + stats.inc (nano::stat::type::local_block_broadcaster, nano::stat::detail::erase_confirmed); + return true; + } + return false; + }); +} + +std::unique_ptr nano::local_block_broadcaster::collect_container_info (const std::string & name) const +{ + nano::lock_guard guard{ mutex }; + + auto composite = std::make_unique (name); + composite->add_component (std::make_unique (container_info{ "local", local_blocks.size (), sizeof (decltype (local_blocks)::value_type) })); + return composite; +} + +nano::block_hash nano::local_block_broadcaster::local_entry::hash () const +{ + return block->hash (); +} diff --git a/nano/node/local_block_broadcaster.hpp b/nano/node/local_block_broadcaster.hpp new file mode 100644 index 0000000000..b4e7093dd6 --- /dev/null +++ b/nano/node/local_block_broadcaster.hpp @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mi = boost::multi_index; + +namespace nano +{ +class node; +class network; +} + +namespace nano +{ +/** + * Broadcasts blocks to the network + * Tracks local blocks for more aggressive propagation + */ +class local_block_broadcaster +{ + enum class broadcast_strategy + { + normal, + aggressive, + }; + +public: + local_block_broadcaster (nano::node &, nano::block_processor &, nano::network &, nano::stats &, bool enabled = false); + ~local_block_broadcaster (); + + void start (); + void stop (); + + std::unique_ptr collect_container_info (std::string const & name) const; + +private: + void run (); + void run_broadcasts (nano::unique_lock &); + void cleanup (); + +private: // Dependencies + nano::node & node; + nano::block_processor & block_processor; + nano::network & network; + nano::stats & stats; + +private: + struct local_entry + { + std::shared_ptr const block; + std::chrono::steady_clock::time_point const arrival; + mutable std::chrono::steady_clock::time_point last_broadcast{}; // Not part of any index + + nano::block_hash hash () const; + }; + + // clang-format off + class tag_sequenced {}; + class tag_hash {}; + + using ordered_locals = boost::multi_index_container>, + mi::hashed_unique, + mi::const_mem_fun> + >>; + // clang-format on + + ordered_locals local_blocks; + +private: + bool enabled{ false }; + + nano::bandwidth_limiter limiter{ broadcast_rate_limit, broadcast_rate_burst_ratio }; + + std::atomic stopped{ false }; + nano::condition_variable condition; + mutable nano::mutex mutex; + std::thread thread; + + // TODO: Make these configurable + static std::size_t constexpr max_size{ 1024 * 8 }; + static std::chrono::seconds constexpr check_interval{ 30 }; + static std::chrono::seconds constexpr broadcast_interval{ 60 }; + static std::size_t constexpr broadcast_rate_limit{ 32 }; + static double constexpr broadcast_rate_burst_ratio{ 3 }; +}; +} diff --git a/nano/node/logging.cpp b/nano/node/logging.cpp deleted file mode 100644 index 5dcfb9f816..0000000000 --- a/nano/node/logging.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_WINDOWS -#else -#define BOOST_LOG_USE_NATIVE_SYSLOG -#include -#endif - -BOOST_LOG_ATTRIBUTE_KEYWORD (severity, "Severity", nano::severity_level) - -boost::shared_ptr> nano::logging::file_sink; -std::atomic_flag nano::logging::logging_already_added ATOMIC_FLAG_INIT; - -void nano::logging::init (std::filesystem::path const & application_path_a) -{ - if (!logging_already_added.test_and_set ()) - { - boost::log::add_common_attributes (); - auto format = boost::log::expressions::stream << boost::log::expressions::attr ("Severity") << boost::log::expressions::smessage; - auto format_with_timestamp = boost::log::expressions::stream << "[" << boost::log::expressions::attr ("TimeStamp") << "]: " << boost::log::expressions::attr ("Severity") << boost::log::expressions::smessage; - - if (log_to_cerr ()) - { - boost::log::add_console_log (std::cerr, boost::log::keywords::format = format_with_timestamp); - } - -#ifdef BOOST_WINDOWS -#else - static auto sys_sink = boost::make_shared> (boost::log::keywords::facility = boost::log::sinks::syslog::user, boost::log::keywords::use_impl = boost::log::sinks::syslog::impl_types::native); - sys_sink->set_formatter (format); - - // Currently only mapping sys log errors - boost::log::sinks::syslog::custom_severity_mapping mapping ("Severity"); - mapping[nano::severity_level::error] = boost::log::sinks::syslog::error; - sys_sink->locked_backend ()->set_severity_mapper (mapping); - - // Only allow messages or error or greater severity to the sys log - sys_sink->set_filter (severity >= nano::severity_level::error); - boost::log::core::get ()->add_sink (sys_sink); -#endif - -//clang-format off -#if BOOST_VERSION < 107000 - if (stable_log_filename) - { - stable_log_filename = false; - std::cerr << "The stable_log_filename config setting is only available when building with Boost 1.70 or later. Reverting to old behavior." << std::endl; - } -#endif - - auto path = application_path_a / "log"; - if (stable_log_filename) - { -#if BOOST_VERSION >= 107000 - auto const file_name = path / "node.log"; - // Logging to node.log and node_ instead of log_.log is deliberate. This way, - // existing log monitoring scripts expecting the old logfile structure will fail immediately instead - // of reading only rotated files with old entries. - file_sink = boost::log::add_file_log (boost::log::keywords::target = path, - boost::log::keywords::file_name = file_name, - boost::log::keywords::target_file_name = path / "node_%Y-%m-%d_%H-%M-%S.%N.log", - boost::log::keywords::open_mode = std::ios_base::out | std::ios_base::app, // append to node.log if it exists - boost::log::keywords::enable_final_rotation = false, // for stable log filenames, don't rotate on destruction - boost::log::keywords::rotation_size = rotation_size, // max file size in bytes before rotation - boost::log::keywords::auto_flush = flush, - boost::log::keywords::scan_method = boost::log::sinks::file::scan_method::scan_matching, - boost::log::keywords::max_size = max_size, // max total size in bytes of all log files - boost::log::keywords::format = format_with_timestamp); - - if (!std::filesystem::exists (file_name)) - { - // Create temp stream to first create the file - std::ofstream stream (file_name.string ()); - } - - // Set permissions before opening otherwise Windows only has read permissions - nano::set_secure_perm_file (file_name); - -#else - debug_assert (false); -#endif - } - else - { - file_sink = boost::log::add_file_log (boost::log::keywords::target = path, - boost::log::keywords::file_name = path / "log_%Y-%m-%d_%H-%M-%S.%N.log", - boost::log::keywords::rotation_size = rotation_size, - boost::log::keywords::auto_flush = flush, - boost::log::keywords::scan_method = boost::log::sinks::file::scan_method::scan_matching, - boost::log::keywords::max_size = max_size, - boost::log::keywords::format = format_with_timestamp); - } - - struct exception_handler - { - void operator() (std::exception const & e) const - { - std::cerr << "Logging exception: " << e.what () << std::endl; - } - }; - - boost::log::core::get ()->set_exception_handler (boost::log::make_exception_handler (exception_handler ())); - } - //clang-format on -} - -void nano::logging::release_file_sink () -{ - if (logging_already_added.test_and_set ()) - { - boost::log::core::get ()->remove_sink (nano::logging::file_sink); - nano::logging::file_sink.reset (); - logging_already_added.clear (); - } -} - -nano::error nano::logging::serialize_toml (nano::tomlconfig & toml) const -{ - toml.put ("ledger", ledger_logging_value, "Log ledger related messages.\ntype:bool"); - toml.put ("ledger_duplicate", ledger_duplicate_logging_value, "Log when a duplicate block is attempted inserted into the ledger.\ntype:bool"); - toml.put ("ledger_rollback", election_fork_tally_logging_value, "Log when a block is replaced in the ledger.\ntype:bool"); - toml.put ("vote", vote_logging_value, "Vote logging. Enabling this option leads to a high volume.\nof log messages which may affect node performance.\ntype:bool"); - toml.put ("rep_crawler", rep_crawler_logging_value, "Rep crawler logging. Enabling this option leads to a high volume.\nof log messages which may affect node performance.\ntype:bool"); - toml.put ("election_expiration", election_expiration_tally_logging_value, "Log election tally on expiration.\ntype:bool"); - toml.put ("election_fork", election_fork_tally_logging_value, "Log election tally when more than one block is seen.\ntype:bool"); - toml.put ("network", network_logging_value, "Log network related messages.\ntype:bool"); - toml.put ("network_timeout", network_timeout_logging_value, "Log TCP timeouts.\ntype:bool"); - toml.put ("network_message", network_message_logging_value, "Log network errors and message details.\ntype:bool"); - toml.put ("network_publish", network_publish_logging_value, "Log publish related network messages.\ntype:bool"); - toml.put ("network_packet", network_packet_logging_value, "Log network packet activity.\ntype:bool"); - toml.put ("network_keepalive", network_keepalive_logging_value, "Log keepalive related messages.\ntype:bool"); - toml.put ("network_node_id_handshake", network_node_id_handshake_logging_value, "Log node-id handshake related messages.\ntype:bool"); - toml.put ("network_telemetry", network_telemetry_logging_value, "Log telemetry related messages.\ntype:bool"); - toml.put ("network_rejected", network_rejected_logging_value, "Log message when a connection is rejected.\ntype:bool"); - toml.put ("node_lifetime_tracing", node_lifetime_tracing_value, "Log node startup and shutdown messages.\ntype:bool"); - toml.put ("insufficient_work", insufficient_work_logging_value, "Log if insufficient work is detected.\ntype:bool"); - toml.put ("log_ipc", log_ipc_value, "Log IPC related activity.\ntype:bool"); - toml.put ("bulk_pull", bulk_pull_logging_value, "Log bulk pull errors and messages.\ntype:bool"); - toml.put ("work_generation_time", work_generation_time_value, "Log work generation timing information.\ntype:bool"); - toml.put ("upnp_details", upnp_details_logging_value, "Log UPNP discovery details..\nWarning: this may include information.\nabout discovered devices, such as product identification. Please review before sharing logs.\ntype:bool"); - toml.put ("timing", timing_logging_value, "Log detailed timing information for various node operations.\ntype:bool"); - toml.put ("active_update", active_update_value, "Log when a block is updated while in active transactions.\ntype:bool"); - toml.put ("election_result", election_result_logging_value, "Log election result when cleaning up election from active election container.\ntype:bool"); - toml.put ("log_to_cerr", log_to_cerr_value, "Log to standard error in addition to the log file. Not recommended for production systems.\ntype:bool"); - toml.put ("max_size", max_size, "Maximum log file size in bytes.\ntype:uint64"); - toml.put ("rotation_size", rotation_size, "Log file rotation size in character count.\ntype:uint64"); - toml.put ("flush", flush, "If enabled, immediately flush new entries to log file.\nWarning: this may negatively affect logging performance.\ntype:bool"); - toml.put ("min_time_between_output", min_time_between_log_output.count (), "Minimum time that must pass for low priority entries to be logged.\nWarning: decreasing this value may result in a very large amount of logs.\ntype:milliseconds"); - toml.put ("single_line_record", single_line_record_value, "Keep log entries on single lines.\ntype:bool"); - toml.put ("stable_log_filename", stable_log_filename, "Append to log/node.log without a timestamp in the filename.\nThe file is not emptied on startup if it exists, but appended to.\ntype:bool"); - - return toml.get_error (); -} - -nano::error nano::logging::deserialize_toml (nano::tomlconfig & toml) -{ - toml.get ("ledger", ledger_logging_value); - toml.get ("ledger_duplicate", ledger_duplicate_logging_value); - toml.get ("ledger_rollback", ledger_rollback_logging_value); - toml.get ("vote", vote_logging_value); - toml.get ("rep_crawler", rep_crawler_logging_value); - toml.get ("election_expiration", election_expiration_tally_logging_value); - toml.get ("election_fork", election_fork_tally_logging_value); - toml.get ("network", network_logging_value); - toml.get ("network_timeout", network_timeout_logging_value); - toml.get ("network_message", network_message_logging_value); - toml.get ("network_publish", network_publish_logging_value); - toml.get ("network_packet", network_packet_logging_value); - toml.get ("network_keepalive", network_keepalive_logging_value); - toml.get ("network_node_id_handshake", network_node_id_handshake_logging_value); - toml.get ("network_telemetry_logging", network_telemetry_logging_value); - toml.get ("network_rejected_logging", network_rejected_logging_value); - toml.get ("node_lifetime_tracing", node_lifetime_tracing_value); - toml.get ("insufficient_work", insufficient_work_logging_value); - toml.get ("log_ipc", log_ipc_value); - toml.get ("bulk_pull", bulk_pull_logging_value); - toml.get ("work_generation_time", work_generation_time_value); - toml.get ("upnp_details", upnp_details_logging_value); - toml.get ("timing", timing_logging_value); - toml.get ("active_update", active_update_value); - toml.get ("election_result", election_result_logging_value); - toml.get ("log_to_cerr", log_to_cerr_value); - toml.get ("flush", flush); - toml.get ("single_line_record", single_line_record_value); - toml.get ("max_size", max_size); - toml.get ("rotation_size", rotation_size); - auto min_time_between_log_output_l = min_time_between_log_output.count (); - toml.get ("min_time_between_output", min_time_between_log_output_l); - min_time_between_log_output = std::chrono::milliseconds (min_time_between_log_output_l); - toml.get ("stable_log_filename", stable_log_filename); - - return toml.get_error (); -} - -bool nano::logging::ledger_logging () const -{ - return ledger_logging_value; -} - -bool nano::logging::ledger_duplicate_logging () const -{ - return ledger_logging () && ledger_duplicate_logging_value; -} - -bool nano::logging::ledger_rollback_logging () const -{ - return ledger_rollback_logging_value; -} - -bool nano::logging::vote_logging () const -{ - return vote_logging_value; -} - -bool nano::logging::rep_crawler_logging () const -{ - return rep_crawler_logging_value; -} - -bool nano::logging::election_expiration_tally_logging () const -{ - return election_expiration_tally_logging_value; -} - -bool nano::logging::election_fork_tally_logging () const -{ - return election_fork_tally_logging_value; -} - -bool nano::logging::network_logging () const -{ - return network_logging_value; -} - -bool nano::logging::network_timeout_logging () const -{ - return network_logging () && network_timeout_logging_value; -} - -bool nano::logging::network_message_logging () const -{ - return network_logging () && network_message_logging_value; -} - -bool nano::logging::network_publish_logging () const -{ - return network_logging () && network_publish_logging_value; -} - -bool nano::logging::network_packet_logging () const -{ - return network_logging () && network_packet_logging_value; -} - -bool nano::logging::network_keepalive_logging () const -{ - return network_logging () && network_keepalive_logging_value; -} - -bool nano::logging::network_node_id_handshake_logging () const -{ - return network_logging () && network_node_id_handshake_logging_value; -} - -bool nano::logging::network_telemetry_logging () const -{ - return network_logging () && network_telemetry_logging_value; -} - -bool nano::logging::network_rejected_logging () const -{ - return network_logging () && network_rejected_logging_value; -} - -bool nano::logging::node_lifetime_tracing () const -{ - return node_lifetime_tracing_value; -} - -bool nano::logging::insufficient_work_logging () const -{ - return network_logging () && insufficient_work_logging_value; -} - -bool nano::logging::log_ipc () const -{ - return network_logging () && log_ipc_value; -} - -bool nano::logging::bulk_pull_logging () const -{ - return network_logging () && bulk_pull_logging_value; -} - -bool nano::logging::callback_logging () const -{ - return network_logging (); -} - -bool nano::logging::work_generation_time () const -{ - return work_generation_time_value; -} - -bool nano::logging::upnp_details_logging () const -{ - return upnp_details_logging_value; -} - -bool nano::logging::timing_logging () const -{ - return timing_logging_value; -} - -bool nano::logging::active_update_logging () const -{ - return active_update_value; -} - -bool nano::logging::election_result_logging () const -{ - return election_result_logging_value; -} - -bool nano::logging::log_to_cerr () const -{ - return log_to_cerr_value; -} - -bool nano::logging::single_line_record () const -{ - return single_line_record_value; -} diff --git a/nano/node/logging.hpp b/nano/node/logging.hpp deleted file mode 100644 index e8f206a51e..0000000000 --- a/nano/node/logging.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include -#include -#include - -#define FATAL_LOG_PREFIX "FATAL ERROR: " - -namespace boost -{ -BOOST_LOG_OPEN_NAMESPACE -namespace sinks -{ - class text_file_backend; - - template - class synchronous_sink; -} - -BOOST_LOG_CLOSE_NAMESPACE - -} - -namespace nano -{ -class tomlconfig; -class logging final -{ -public: - nano::error serialize_toml (nano::tomlconfig &) const; - nano::error deserialize_toml (nano::tomlconfig &); - bool ledger_logging () const; - bool ledger_duplicate_logging () const; - bool ledger_rollback_logging () const; - bool vote_logging () const; - bool rep_crawler_logging () const; - bool election_fork_tally_logging () const; - bool election_expiration_tally_logging () const; - bool network_logging () const; - bool network_timeout_logging () const; - bool network_message_logging () const; - bool network_publish_logging () const; - bool network_packet_logging () const; - bool network_keepalive_logging () const; - bool network_node_id_handshake_logging () const; - bool network_telemetry_logging () const; - bool network_rejected_logging () const; - bool node_lifetime_tracing () const; - bool insufficient_work_logging () const; - bool upnp_details_logging () const; - bool timing_logging () const; - bool log_ipc () const; - bool bulk_pull_logging () const; - bool callback_logging () const; - bool work_generation_time () const; - bool active_update_logging () const; - bool election_result_logging () const; - bool log_to_cerr () const; - bool single_line_record () const; - void init (std::filesystem::path const &); - - bool ledger_logging_value{ false }; - bool ledger_duplicate_logging_value{ false }; - bool ledger_rollback_logging_value{ false }; - bool vote_logging_value{ false }; - bool rep_crawler_logging_value{ false }; - bool election_fork_tally_logging_value{ false }; - bool election_expiration_tally_logging_value{ false }; - bool network_logging_value{ true }; - bool network_timeout_logging_value{ false }; - bool network_message_logging_value{ false }; - bool network_publish_logging_value{ false }; - bool network_packet_logging_value{ false }; - bool network_keepalive_logging_value{ false }; - bool network_node_id_handshake_logging_value{ false }; - bool network_telemetry_logging_value{ false }; - bool network_rejected_logging_value{ false }; - bool node_lifetime_tracing_value{ false }; - bool insufficient_work_logging_value{ true }; - bool log_ipc_value{ true }; - bool bulk_pull_logging_value{ false }; - bool work_generation_time_value{ true }; - bool upnp_details_logging_value{ false }; - bool timing_logging_value{ false }; - bool active_update_value{ false }; - bool election_result_logging_value{ false }; - bool log_to_cerr_value{ false }; - bool flush{ true }; - uintmax_t max_size{ 128 * 1024 * 1024 }; - uintmax_t rotation_size{ 4 * 1024 * 1024 }; - bool stable_log_filename{ false }; - std::chrono::milliseconds min_time_between_log_output{ 5 }; - bool single_line_record_value{ false }; - static void release_file_sink (); - -private: - static boost::shared_ptr> file_sink; - static std::atomic_flag logging_already_added; -}; -} diff --git a/nano/node/make_store.cpp b/nano/node/make_store.cpp index 7f24c649cf..c3c8c28105 100644 --- a/nano/node/make_store.cpp +++ b/nano/node/make_store.cpp @@ -2,7 +2,7 @@ #include #include -std::unique_ptr nano::make_store (nano::logger_mt & logger, std::filesystem::path const & path, nano::ledger_constants & constants, bool read_only, bool add_db_postfix, nano::rocksdb_config const & rocksdb_config, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade) +std::unique_ptr nano::make_store (nano::logger & logger, std::filesystem::path const & path, nano::ledger_constants & constants, bool read_only, bool add_db_postfix, nano::rocksdb_config const & rocksdb_config, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade) { if (rocksdb_config.enable) { diff --git a/nano/node/make_store.hpp b/nano/node/make_store.hpp index 1e7bdd2dc1..5f5b5f9372 100644 --- a/nano/node/make_store.hpp +++ b/nano/node/make_store.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -22,5 +22,5 @@ class component; namespace nano { -std::unique_ptr make_store (nano::logger_mt & logger, std::filesystem::path const & path, nano::ledger_constants & constants, bool open_read_only = false, bool add_db_postfix = true, nano::rocksdb_config const & rocksdb_config = nano::rocksdb_config{}, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false); +std::unique_ptr make_store (nano::logger &, std::filesystem::path const & path, nano::ledger_constants & constants, bool open_read_only = false, bool add_db_postfix = true, nano::rocksdb_config const & rocksdb_config = nano::rocksdb_config{}, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false); } diff --git a/nano/node/messages.cpp b/nano/node/messages.cpp index 3b6079b432..b4a19784fe 100644 --- a/nano/node/messages.cpp +++ b/nano/node/messages.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -82,105 +84,6 @@ bool nano::message_header::deserialize (nano::stream & stream_a) return error; } -std::string nano::to_string (nano::message_type type) -{ - switch (type) - { - case nano::message_type::invalid: - return "invalid"; - case nano::message_type::not_a_type: - return "not_a_type"; - case nano::message_type::keepalive: - return "keepalive"; - case nano::message_type::publish: - return "publish"; - case nano::message_type::confirm_req: - return "confirm_req"; - case nano::message_type::confirm_ack: - return "confirm_ack"; - case nano::message_type::bulk_pull: - return "bulk_pull"; - case nano::message_type::bulk_push: - return "bulk_push"; - case nano::message_type::frontier_req: - return "frontier_req"; - case nano::message_type::node_id_handshake: - return "node_id_handshake"; - case nano::message_type::bulk_pull_account: - return "bulk_pull_account"; - case nano::message_type::telemetry_req: - return "telemetry_req"; - case nano::message_type::telemetry_ack: - return "telemetry_ack"; - case nano::message_type::asc_pull_req: - return "asc_pull_req"; - case nano::message_type::asc_pull_ack: - return "asc_pull_ack"; - // default case intentionally omitted to cause warnings for unhandled enums - } - - return "n/a"; -} - -nano::stat::detail nano::to_stat_detail (nano::message_type type) -{ - switch (type) - { - case nano::message_type::invalid: - return nano::stat::detail::invalid; - case nano::message_type::not_a_type: - return nano::stat::detail::not_a_type; - case nano::message_type::keepalive: - return nano::stat::detail::keepalive; - case nano::message_type::publish: - return nano::stat::detail::publish; - case nano::message_type::confirm_req: - return nano::stat::detail::confirm_req; - case nano::message_type::confirm_ack: - return nano::stat::detail::confirm_ack; - case nano::message_type::bulk_pull: - return nano::stat::detail::bulk_pull; - case nano::message_type::bulk_push: - return nano::stat::detail::bulk_push; - case nano::message_type::frontier_req: - return nano::stat::detail::frontier_req; - case nano::message_type::node_id_handshake: - return nano::stat::detail::node_id_handshake; - case nano::message_type::bulk_pull_account: - return nano::stat::detail::bulk_pull_account; - case nano::message_type::telemetry_req: - return nano::stat::detail::telemetry_req; - case nano::message_type::telemetry_ack: - return nano::stat::detail::telemetry_ack; - case nano::message_type::asc_pull_req: - return nano::stat::detail::asc_pull_req; - case nano::message_type::asc_pull_ack: - return nano::stat::detail::asc_pull_ack; - // default case intentionally omitted to cause warnings for unhandled enums - } - debug_assert (false); - return {}; -} - -std::string nano::message_header::to_string () const -{ - // Cast to uint16_t to get integer value since uint8_t is treated as an unsigned char in string formatting. - uint16_t type_l = static_cast (type); - uint16_t version_max_l = static_cast (version_max); - uint16_t version_using_l = static_cast (version_using); - uint16_t version_min_l = static_cast (version_min); - std::string type_text = nano::to_string (type); - - std::stringstream stream; - - stream << boost::format ("NetID: %1%(%2%), ") % nano::to_string_hex (static_cast (network)) % nano::network::to_string (network); - stream << boost::format ("VerMaxUsingMin: %1%/%2%/%3%, ") % version_max_l % version_using_l % version_min_l; - stream << boost::format ("MsgType: %1%(%2%), ") % type_l % type_text; - stream << boost::format ("Extensions: %1%") % nano::to_string_hex (static_cast (extensions.to_ulong ())); - - return stream.str (); -} - nano::block_type nano::message_header::block_type () const { return static_cast (((extensions & block_type_mask) >> 8).to_ullong ()); @@ -396,6 +299,17 @@ bool nano::message_header::is_valid_message_type () const } } +void nano::message_header::operator() (nano::object_stream & obs) const +{ + obs.write ("type", type); + obs.write ("network", to_string (network)); + obs.write ("network_raw", static_cast (network)); + obs.write ("version", static_cast (version_using)); + obs.write ("version_min", static_cast (version_min)); + obs.write ("version_max", static_cast (version_max)); + obs.write ("extensions", static_cast (extensions.to_ulong ())); +} + /* * message */ @@ -428,6 +342,11 @@ nano::message_type nano::message::type () const return header.type; } +void nano::message::operator() (nano::object_stream & obs) const +{ + obs.write ("header", header); +} + /* * keepalive */ @@ -493,19 +412,11 @@ bool nano::keepalive::operator== (nano::keepalive const & other_a) const return peers == other_a.peers; } -std::string nano::keepalive::to_string () const +void nano::keepalive::operator() (nano::object_stream & obs) const { - std::stringstream stream; - - stream << header.to_string (); - - for (auto peer = peers.begin (); peer != peers.end (); ++peer) - { - stream << "\n" - << peer->address ().to_string () + ":" + std::to_string (peer->port ()); - } + nano::message::operator() (obs); // Write common data - return stream.str (); + obs.write_range ("peers", peers); } /* @@ -554,9 +465,11 @@ bool nano::publish::operator== (nano::publish const & other_a) const return *block == *other_a.block; } -std::string nano::publish::to_string () const +void nano::publish::operator() (nano::object_stream & obs) const { - return header.to_string () + "\n" + block->to_json (); + nano::message::operator() (obs); // Write common data + + obs.write ("block", block); } /* @@ -659,19 +572,6 @@ bool nano::confirm_req::operator== (nano::confirm_req const & other_a) const return equal; } -std::string nano::confirm_req::roots_string () const -{ - std::string result; - for (auto & root_hash : roots_hashes) - { - result += root_hash.first.to_string (); - result += ":"; - result += root_hash.second.to_string (); - result += ", "; - } - return result; -} - uint8_t nano::confirm_req::hash_count (const nano::message_header & header) { if (header.confirm_is_v2 ()) @@ -690,16 +590,16 @@ std::size_t nano::confirm_req::size (nano::message_header const & header) return count * (sizeof (decltype (roots_hashes)::value_type::first) + sizeof (decltype (roots_hashes)::value_type::second)); } -std::string nano::confirm_req::to_string () const +void nano::confirm_req::operator() (nano::object_stream & obs) const { - std::string s = header.to_string (); - - for (auto && roots_hash : roots_hashes) - { - s += "\n" + roots_hash.first.to_string () + ":" + roots_hash.second.to_string (); - } + nano::message::operator() (obs); // Write common data - return s; + // Write roots as: [ { root: ##, hash: ## } ,...] + obs.write_range ("roots", roots_hashes, [] (auto const & root_hash, nano::object_stream & obs) { + auto [root, hash] = root_hash; + obs.write ("root", root); + obs.write ("hash", hash); + }); } /* @@ -771,9 +671,11 @@ std::size_t nano::confirm_ack::size (const nano::message_header & header) return nano::vote::size (count); } -std::string nano::confirm_ack::to_string () const +void nano::confirm_ack::operator() (nano::object_stream & obs) const { - return header.to_string () + "\n" + vote->to_json (); + nano::message::operator() (obs); // Write common data + + obs.write ("vote", vote); } /* @@ -830,13 +732,13 @@ bool nano::frontier_req::operator== (nano::frontier_req const & other_a) const return start == other_a.start && age == other_a.age && count == other_a.count; } -std::string nano::frontier_req::to_string () const +void nano::frontier_req::operator() (nano::object_stream & obs) const { - std::string s = header.to_string (); - s += "\nstart=" + start.to_string (); - s += " maxage=" + std::to_string (age); - s += " count=" + std::to_string (count); - return s; + nano::message::operator() (obs); // Write common data + + obs.write ("start", start); + obs.write ("age", age); + obs.write ("count", count); } /* @@ -939,13 +841,13 @@ void nano::bulk_pull::set_count_present (bool value_a) header.extensions.set (count_present_flag, value_a); } -std::string nano::bulk_pull::to_string () const +void nano::bulk_pull::operator() (nano::object_stream & obs) const { - std::string s = header.to_string (); - s += "\nstart=" + start.to_string (); - s += " end=" + end.to_string (); - s += " cnt=" + std::to_string (count); - return s; + nano::message::operator() (obs); // Write common data + + obs.write ("start", start); + obs.write ("end", end); + obs.write ("count", count); } /* @@ -997,27 +899,13 @@ bool nano::bulk_pull_account::deserialize (nano::stream & stream_a) return error; } -std::string nano::bulk_pull_account::to_string () const +void nano::bulk_pull_account::operator() (nano::object_stream & obs) const { - std::string s = header.to_string () + "\n"; - s += "acc=" + account.to_string (); - s += " min=" + minimum_amount.to_string (); - switch (flags) - { - case bulk_pull_account_flags::pending_hash_and_amount: - s += " pending_hash_and_amount"; - break; - case bulk_pull_account_flags::pending_address_only: - s += " pending_address_only"; - break; - case bulk_pull_account_flags::pending_hash_amount_and_address: - s += " pending_hash_amount_and_address"; - break; - default: - s += " unknown flags"; - break; - } - return s; + nano::message::operator() (obs); // Write common data + + obs.write ("account", account); + obs.write ("minimum_amount", minimum_amount); + obs.write ("flags", static_cast (flags)); // TODO: Prettier flag printing } /* @@ -1050,6 +938,11 @@ void nano::bulk_push::visit (nano::message_visitor & visitor_a) const visitor_a.bulk_push (*this); } +void nano::bulk_push::operator() (nano::object_stream & obs) const +{ + nano::message::operator() (obs); // Write common data +} + /* * telemetry_req */ @@ -1080,9 +973,9 @@ void nano::telemetry_req::visit (nano::message_visitor & visitor_a) const visitor_a.telemetry_req (*this); } -std::string nano::telemetry_req::to_string () const +void nano::telemetry_req::operator() (nano::object_stream & obs) const { - return header.to_string (); + nano::message::operator() (obs); // Write common data } /* @@ -1160,18 +1053,14 @@ bool nano::telemetry_ack::is_empty_payload () const return size () == 0; } -std::string nano::telemetry_ack::to_string () const +void nano::telemetry_ack::operator() (nano::object_stream & obs) const { - std::string s = header.to_string () + "\n"; - if (is_empty_payload ()) - { - s += "empty telemetry payload"; - } - else + nano::message::operator() (obs); // Write common data + + if (!is_empty_payload ()) { - s += data.to_string (); + obs.write ("data", data); } - return s; } /* @@ -1327,15 +1216,6 @@ nano::error nano::telemetry_data::deserialize_json (nano::jsonconfig & json, boo return json.get_error (); } -std::string nano::telemetry_data::to_string () const -{ - nano::jsonconfig jc; - serialize_json (jc, true); - std::stringstream ss; - jc.write (ss); - return ss.str (); -} - bool nano::telemetry_data::operator== (nano::telemetry_data const & data_a) const { return (signature == data_a.signature && node_id == data_a.node_id && block_count == data_a.block_count && cemented_count == data_a.cemented_count && unchecked_count == data_a.unchecked_count && account_count == data_a.account_count && bandwidth_cap == data_a.bandwidth_cap && uptime == data_a.uptime && peer_count == data_a.peer_count && protocol_version == data_a.protocol_version && genesis_block == data_a.genesis_block && major_version == data_a.major_version && minor_version == data_a.minor_version && patch_version == data_a.patch_version && pre_release_version == data_a.pre_release_version && maker == data_a.maker && timestamp == data_a.timestamp && active_difficulty == data_a.active_difficulty && unknown_data == data_a.unknown_data); @@ -1369,6 +1249,11 @@ bool nano::telemetry_data::validate_signature () const return nano::validate_message (node_id, bytes.data (), bytes.size (), signature); } +void nano::telemetry_data::operator() (nano::object_stream & obs) const +{ + // TODO: Telemetry data +} + /* * node_id_handshake */ @@ -1486,19 +1371,12 @@ std::size_t nano::node_id_handshake::size (nano::message_header const & header) return result; } -std::string nano::node_id_handshake::to_string () const +void nano::node_id_handshake::operator() (nano::object_stream & obs) const { - std::string s = header.to_string (); - if (query) - { - s += "\ncookie=" + query->cookie.to_string (); - } - if (response) - { - s += "\nresp_node_id=" + response->node_id.to_string (); - s += "\nresp_sig=" + response->signature.to_string (); - } - return s; + nano::message::operator() (obs); // Write common data + + obs.write ("query", query); + obs.write ("response", response); } /* @@ -1515,6 +1393,11 @@ void nano::node_id_handshake::query_payload::deserialize (nano::stream & stream) nano::read (stream, cookie); } +void nano::node_id_handshake::query_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("cookie", cookie); +} + /* * node_id_handshake::response_payload */ @@ -1598,6 +1481,19 @@ bool nano::node_id_handshake::response_payload::validate (const nano::uint256_un return true; // OK } +void nano::node_id_handshake::response_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("node_id", node_id); + obs.write ("signature", signature); + + obs.write ("v2", v2.has_value ()); + if (v2) + { + obs.write ("salt", v2->salt); + obs.write ("genesis", v2->genesis); + } +} + /* * asc_pull_req */ @@ -1728,35 +1624,16 @@ bool nano::asc_pull_req::verify_consistency () const return true; // Just for convenience of calling from asserts } -std::string nano::asc_pull_req::to_string () const +void nano::asc_pull_req::operator() (nano::object_stream & obs) const { - std::string s = header.to_string () + "\n"; - - std::visit ([&s] (auto && arg) { - using T = std::decay_t; - - if constexpr (std::is_same_v) - { - s += "missing payload"; - } + nano::message::operator() (obs); // Write common data - else if constexpr (std::is_same_v) - { - s += "acc:" + arg.start.to_string (); - s += " max block count:" + to_string_hex (static_cast (arg.count)); - s += " hash type:" + to_string_hex (static_cast (arg.start_type)); - } - - else if constexpr (std::is_same_v) - { - s += "target:" + arg.target.to_string (); - s += " hash type:" + to_string_hex (static_cast (arg.target_type)); - } - }, - payload); + obs.write ("type", type); + obs.write ("id", id); - return s; + std::visit ([&obs] (auto && pld) { pld (obs); }, payload); // Log payload } + /* * asc_pull_req::blocks_payload */ @@ -1775,6 +1652,13 @@ void nano::asc_pull_req::blocks_payload::deserialize (nano::stream & stream) nano::read (stream, start_type); } +void nano::asc_pull_req::blocks_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("start", start); + obs.write ("start_type", start_type); + obs.write ("count", count); +} + /* * asc_pull_req::account_info_payload */ @@ -1791,6 +1675,12 @@ void nano::asc_pull_req::account_info_payload::deserialize (stream & stream) nano::read (stream, target_type); } +void nano::asc_pull_req::account_info_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("target", target); + obs.write ("target_type", target_type); +} + /* * asc_pull_req::frontiers_payload */ @@ -1807,6 +1697,12 @@ void nano::asc_pull_req::frontiers_payload::deserialize (nano::stream & stream) nano::read_big_endian (stream, count); } +void nano::asc_pull_req::frontiers_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("start", start); + obs.write ("count", count); +} + /* * asc_pull_ack */ @@ -1938,43 +1834,14 @@ bool nano::asc_pull_ack::verify_consistency () const return true; // Just for convenience of calling from asserts } -std::string nano::asc_pull_ack::to_string () const +void nano::asc_pull_ack::operator() (nano::object_stream & obs) const { - std::string s = header.to_string () + "\n"; - - std::visit ([&s] (auto && arg) { - using T = std::decay_t; - - if constexpr (std::is_same_v) - { - s += "missing payload"; - } + nano::message::operator() (obs); // Write common data - else if constexpr (std::is_same_v) - { - auto block = std::begin (arg.blocks); - auto end_block = std::end (arg.blocks); - - while (block != end_block) - { - s += (*block)->to_json (); - ++block; - } - } + obs.write ("type", type); + obs.write ("id", id); - else if constexpr (std::is_same_v) - { - s += "account public key:" + arg.account.to_account (); - s += " account open:" + arg.account_open.to_string (); - s += " account head:" + arg.account_head.to_string (); - s += " block count:" + to_string_hex (arg.account_block_count); - s += " confirmation frontier:" + arg.account_conf_frontier.to_string (); - s += " confirmation height:" + to_string_hex (arg.account_conf_height); - } - }, - payload); - - return s; + std::visit ([&obs] (auto && pld) { pld (obs); }, payload); // Log payload } /* @@ -2004,6 +1871,11 @@ void nano::asc_pull_ack::blocks_payload::deserialize (nano::stream & stream) } } +void nano::asc_pull_ack::blocks_payload::operator() (nano::object_stream & obs) const +{ + obs.write_range ("blocks", blocks); +} + /* * asc_pull_ack::account_info_payload */ @@ -2028,6 +1900,16 @@ void nano::asc_pull_ack::account_info_payload::deserialize (nano::stream & strea nano::read_big_endian (stream, account_conf_height); } +void nano::asc_pull_ack::account_info_payload::operator() (nano::object_stream & obs) const +{ + obs.write ("account", account); + obs.write ("open", account_open); + obs.write ("head", account_head); + obs.write ("block_count", account_block_count); + obs.write ("conf_frontier", account_conf_frontier); + obs.write ("conf_height", account_conf_height); +} + /* * asc_pull_ack::frontiers_payload */ @@ -2068,3 +1950,35 @@ void nano::asc_pull_ack::frontiers_payload::deserialize (nano::stream & stream) current = deserialize_frontier (stream); } } + +void nano::asc_pull_ack::frontiers_payload::operator() (nano::object_stream & obs) const +{ + obs.write_range ("frontiers", frontiers, [] (auto const & entry, nano::object_stream & obs) { + auto & [account, hash] = entry; + obs.write ("account", account); + obs.write ("hash", hash); + }); +} + +/* + * + */ + +std::string_view nano::to_string (nano::message_type type) +{ + return magic_enum::enum_name (type); +} + +nano::stat::detail nano::to_stat_detail (nano::message_type type) +{ + auto value = magic_enum::enum_cast (magic_enum::enum_name (type)); + debug_assert (value); + return value.value_or (nano::stat::detail{}); +} + +nano::log::detail nano::to_log_detail (nano::message_type type) +{ + auto value = magic_enum::enum_cast (magic_enum::enum_name (type)); + debug_assert (value); + return value.value_or (nano::log::detail{}); +} diff --git a/nano/node/messages.hpp b/nano/node/messages.hpp index 5c22118695..11d96d6bad 100644 --- a/nano/node/messages.hpp +++ b/nano/node/messages.hpp @@ -1,11 +1,14 @@ #pragma once #include -#include +#include #include #include #include +#include +#include #include +#include #include #include #include @@ -44,8 +47,9 @@ enum class message_type : uint8_t asc_pull_ack = 0x0f, }; -std::string to_string (message_type); -stat::detail to_stat_detail (message_type); +std::string_view to_string (nano::message_type); +stat::detail to_stat_detail (nano::message_type); +log::detail to_log_detail (nano::message_type); enum class bulk_pull_account_flags : uint8_t { @@ -67,8 +71,6 @@ class message_header final void serialize (nano::stream &) const; bool deserialize (nano::stream &); - std::string to_string () const; - public: // Payload nano::networks network; uint8_t version_max; @@ -112,6 +114,9 @@ class message_header final static extensions_bitset_t constexpr count_v2_mask_left{ 0xf000 }; static extensions_bitset_t constexpr count_v2_mask_right{ 0x00f0 }; static extensions_bitset_t constexpr telemetry_size_mask{ 0x3ff }; + +public: // Logging + void operator() (nano::object_stream &) const; }; class message @@ -130,6 +135,9 @@ class message public: nano::message_header header; + +public: // Logging + virtual void operator() (nano::object_stream &) const; }; class keepalive final : public message @@ -143,7 +151,9 @@ class keepalive final : public message bool operator== (nano::keepalive const &) const; std::array peers; static std::size_t constexpr size = 8 * (16 + 2); - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class publish final : public message @@ -157,7 +167,9 @@ class publish final : public message bool operator== (nano::publish const &) const; std::shared_ptr block; nano::uint128_t digest{ 0 }; - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class confirm_req final : public message @@ -172,7 +184,6 @@ class confirm_req final : public message void visit (nano::message_visitor &) const override; bool operator== (nano::confirm_req const &) const; std::string roots_string () const; - std::string to_string () const; static std::size_t size (nano::message_header const &); @@ -181,6 +192,9 @@ class confirm_req final : public message public: // Payload std::vector> roots_hashes; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class confirm_ack final : public message @@ -192,7 +206,6 @@ class confirm_ack final : public message void serialize (nano::stream &) const override; void visit (nano::message_visitor &) const override; bool operator== (nano::confirm_ack const &) const; - std::string to_string () const; static std::size_t size (nano::message_header const &); @@ -201,6 +214,9 @@ class confirm_ack final : public message public: // Payload std::shared_ptr vote; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class frontier_req final : public message @@ -216,7 +232,9 @@ class frontier_req final : public message uint32_t age; uint32_t count; static std::size_t constexpr size = sizeof (start) + sizeof (age) + sizeof (count); - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; enum class telemetry_maker : uint8_t @@ -256,13 +274,16 @@ class telemetry_data bool validate_signature () const; bool operator== (nano::telemetry_data const &) const; bool operator!= (nano::telemetry_data const &) const; - std::string to_string () const; // Size does not include unknown_data static auto constexpr size = sizeof (signature) + sizeof (node_id) + sizeof (block_count) + sizeof (cemented_count) + sizeof (unchecked_count) + sizeof (account_count) + sizeof (bandwidth_cap) + sizeof (peer_count) + sizeof (protocol_version) + sizeof (uptime) + sizeof (genesis_block) + sizeof (major_version) + sizeof (minor_version) + sizeof (patch_version) + sizeof (pre_release_version) + sizeof (maker) + sizeof (uint64_t) + sizeof (active_difficulty); static auto constexpr latest_size = size; // This needs to be updated for each new telemetry version + private: void serialize_without_signature (nano::stream &) const; + +public: // Logging + void operator() (nano::object_stream &) const; }; class telemetry_req final : public message @@ -273,7 +294,9 @@ class telemetry_req final : public message void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void visit (nano::message_visitor &) const override; - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class telemetry_ack final : public message @@ -287,9 +310,11 @@ class telemetry_ack final : public message bool deserialize (nano::stream &); uint16_t size () const; bool is_empty_payload () const; - std::string to_string () const; static uint16_t size (nano::message_header const &); nano::telemetry_data data; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class bulk_pull final : public message @@ -309,7 +334,9 @@ class bulk_pull final : public message static std::size_t constexpr count_present_flag = nano::message_header::bulk_pull_count_present_flag; static std::size_t constexpr extended_parameters_size = 8; static std::size_t constexpr size = sizeof (start) + sizeof (end); - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class bulk_pull_account final : public message @@ -324,7 +351,9 @@ class bulk_pull_account final : public message nano::amount minimum_amount; bulk_pull_account_flags flags; static std::size_t constexpr size = sizeof (account) + sizeof (minimum_amount) + sizeof (bulk_pull_account_flags); - std::string to_string () const; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class bulk_push final : public message @@ -335,6 +364,9 @@ class bulk_push final : public message void serialize (nano::stream &) const override; bool deserialize (nano::stream &); void visit (nano::message_visitor &) const override; + +public: // Logging + void operator() (nano::object_stream &) const override; }; class node_id_handshake final : public message @@ -350,6 +382,9 @@ class node_id_handshake final : public message public: nano::uint256_union cookie; + + public: // Logging + void operator() (nano::object_stream &) const; }; class response_payload @@ -380,6 +415,9 @@ class node_id_handshake final : public message static std::size_t constexpr size_v1 = sizeof (nano::account) + sizeof (nano::signature); static std::size_t constexpr size_v2 = sizeof (nano::account) + sizeof (nano::signature) + sizeof (v2_payload); static std::size_t size (nano::message_header const &); + + public: // Logging + void operator() (nano::object_stream &) const; }; public: @@ -392,7 +430,6 @@ class node_id_handshake final : public message void visit (nano::message_visitor &) const override; std::size_t size () const; static std::size_t size (nano::message_header const &); - std::string to_string () const; public: // Header static uint8_t constexpr query_flag = 0; @@ -407,6 +444,9 @@ class node_id_handshake final : public message public: // Payload std::optional query; std::optional response; + +public: // Logging + void operator() (nano::object_stream &) const override; }; /** @@ -432,6 +472,10 @@ struct empty_payload { debug_assert (false); } + void operator() (nano::object_stream &) const + { + debug_assert (false); + } }; /** @@ -459,7 +503,6 @@ class asc_pull_req final : public message void serialize_payload (nano::stream &) const; void deserialize_payload (nano::stream &); - std::string to_string () const; private: // Debug /** @@ -479,10 +522,13 @@ class asc_pull_req final : public message void serialize (nano::stream &) const; void deserialize (nano::stream &); - // Payload + public: // Payload nano::hash_or_account start{ 0 }; uint8_t count{ 0 }; hash_type start_type{}; + + public: // Logging + void operator() (nano::object_stream &) const; }; struct account_info_payload @@ -490,9 +536,12 @@ class asc_pull_req final : public message void serialize (nano::stream &) const; void deserialize (nano::stream &); - // Payload + public: // Payload nano::hash_or_account target{ 0 }; hash_type target_type{}; + + public: // Logging + void operator() (nano::object_stream &) const; }; struct frontiers_payload @@ -500,9 +549,12 @@ class asc_pull_req final : public message void serialize (nano::stream &) const; void deserialize (nano::stream &); - // Payload + public: // Payload nano::account start{ 0 }; uint16_t count{ 0 }; + + public: // Logging + void operator() (nano::object_stream &) const; }; public: // Payload @@ -515,6 +567,9 @@ class asc_pull_req final : public message public: /** Size of message without payload */ constexpr static std::size_t partial_size = sizeof (type) + sizeof (id); + +public: // Logging + void operator() (nano::object_stream &) const override; }; /** @@ -542,7 +597,6 @@ class asc_pull_ack final : public message void serialize_payload (nano::stream &) const; void deserialize_payload (nano::stream &); - std::string to_string () const; private: // Debug /** @@ -559,8 +613,11 @@ class asc_pull_ack final : public message void serialize (nano::stream &) const; void deserialize (nano::stream &); - // Payload + public: // Payload std::vector> blocks; + + public: // Logging + void operator() (nano::object_stream &) const; }; struct account_info_payload @@ -568,13 +625,16 @@ class asc_pull_ack final : public message void serialize (nano::stream &) const; void deserialize (nano::stream &); - // Payload + public: // Payload nano::account account{ 0 }; nano::block_hash account_open{ 0 }; nano::block_hash account_head{ 0 }; uint64_t account_block_count{ 0 }; nano::block_hash account_conf_frontier{ 0 }; uint64_t account_conf_height{ 0 }; + + public: // Logging + void operator() (nano::object_stream &) const; }; struct frontiers_payload @@ -590,8 +650,11 @@ class asc_pull_ack final : public message static void serialize_frontier (nano::stream &, frontier const &); static frontier deserialize_frontier (nano::stream &); - // Payload + public: // Payload std::vector frontiers; + + public: // Logging + void operator() (nano::object_stream &) const; }; public: // Payload @@ -604,6 +667,9 @@ class asc_pull_ack final : public message public: /** Size of message without payload */ constexpr static std::size_t partial_size = sizeof (type) + sizeof (id); + +public: // Logging + void operator() (nano::object_stream &) const override; }; class message_visitor diff --git a/nano/node/network.cpp b/nano/node/network.cpp index a9c1974399..80660cad00 100644 --- a/nano/node/network.cpp +++ b/nano/node/network.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -27,10 +29,9 @@ nano::network::network (nano::node & node_a, uint16_t port_a) : port (port_a), disconnect_observer ([] () {}) { - // TCP for (std::size_t i = 0; i < node.config.network_threads && !node.flags.disable_tcp_realtime; ++i) { - packet_processing_threads.emplace_back (nano::thread_attributes::get_default (), [this] () { + packet_processing_threads.emplace_back (nano::thread_attributes::get_default (), [this, i] () { nano::thread_role::set (nano::thread_role::name::packet_processing); try { @@ -38,28 +39,24 @@ nano::network::network (nano::node & node_a, uint16_t port_a) : } catch (boost::system::error_code & ec) { - this->node.logger.always_log (FATAL_LOG_PREFIX, ec.message ()); + node.logger.critical (nano::log::type::network, "Error: {}", ec.message ()); release_assert (false); } catch (std::error_code & ec) { - this->node.logger.always_log (FATAL_LOG_PREFIX, ec.message ()); + node.logger.critical (nano::log::type::network, "Error: {}", ec.message ()); release_assert (false); } catch (std::runtime_error & err) { - this->node.logger.always_log (FATAL_LOG_PREFIX, err.what ()); + node.logger.critical (nano::log::type::network, "Error: {}", err.what ()); release_assert (false); } catch (...) { - this->node.logger.always_log (FATAL_LOG_PREFIX, "Unknown exception"); + node.logger.critical (nano::log::type::network, "Unknown error"); release_assert (false); } - if (this->node.config.logging.network_packet_logging ()) - { - this->node.logger.try_log ("Exiting TCP packet processing thread"); - } }); } } @@ -131,10 +128,11 @@ void nano::network::send_node_id_handshake (std::shared_ptrget_endpoint () % (query ? query->cookie.to_string () : std::string ("[none]")) % (respond_to ? respond_to->to_string () : std::string ("[none]")) % (response ? response->signature.to_string () : std::string ("[none]")))); - } + node.logger.debug (nano::log::type::network, "Node ID handshake sent to: {} (query: {}, respond to: {}, signature: {})", + nano::util::to_str (channel_a->get_endpoint ()), + (query ? query->cookie.to_string () : ""), + (respond_to ? respond_to->to_string () : ""), + (response ? response->signature.to_string () : "")); channel_a->send (message); } @@ -222,163 +220,27 @@ void nano::network::flood_block_many (std::deque> b } } -void nano::network::send_confirm_req (std::shared_ptr const & channel_a, std::pair const & hash_root_a) +void nano::network::send_confirm_req (std::shared_ptr const & channel_a, std::pair const & hash_root_a) { + auto & [hash, root] = hash_root_a; // Confirmation request with hash + root - nano::confirm_req req (node.network_params.network, hash_root_a.first, hash_root_a.second); + nano::confirm_req req (node.network_params.network, hash, root); channel_a->send (req); } -void nano::network::broadcast_confirm_req (std::shared_ptr const & block_a) -{ - auto list (std::make_shared>> (node.rep_crawler.representative_endpoints (std::numeric_limits::max ()))); - if (list->empty () || node.rep_crawler.total_weight () < node.online_reps.delta ()) - { - // broadcast request to all peers (with max limit 2 * sqrt (peers count)) - auto peers (node.network.list (std::min (100, node.network.fanout (2.0)))); - list->clear (); - list->insert (list->end (), peers.begin (), peers.end ()); - } - - /* - * In either case (broadcasting to all representatives, or broadcasting to - * all peers because there are not enough connected representatives), - * limit each instance to a single random up-to-32 selection. The invoker - * of "broadcast_confirm_req" will be responsible for calling it again - * if the votes for a block have not arrived in time. - */ - std::size_t const max_endpoints = 32; - nano::random_pool_shuffle (list->begin (), list->end ()); - if (list->size () > max_endpoints) - { - list->erase (list->begin () + max_endpoints, list->end ()); - } - - broadcast_confirm_req_base (block_a, list, 0); -} - -void nano::network::broadcast_confirm_req_base (std::shared_ptr const & block_a, std::shared_ptr>> const & endpoints_a, unsigned delay_a, bool resumption) -{ - std::size_t const max_reps = 10; - if (!resumption && node.config.logging.network_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Broadcasting confirm req for block %1% to %2% representatives") % block_a->hash ().to_string () % endpoints_a->size ())); - } - auto count (0); - while (!endpoints_a->empty () && count < max_reps) - { - auto channel (endpoints_a->back ()); - send_confirm_req (channel, std::make_pair (block_a->hash (), block_a->root ().as_block_hash ())); - endpoints_a->pop_back (); - count++; - } - if (!endpoints_a->empty ()) - { - delay_a += std::rand () % broadcast_interval_ms; - - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (delay_a), [node_w, block_a, endpoints_a, delay_a] () { - if (auto node_l = node_w.lock ()) - { - node_l->network.broadcast_confirm_req_base (block_a, endpoints_a, delay_a, true); - } - }); - } -} - -void nano::network::broadcast_confirm_req_batched_many (std::unordered_map, std::deque>> request_bundle_a, std::function callback_a, unsigned delay_a, bool resumption_a) -{ - if (!resumption_a && node.config.logging.network_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Broadcasting batch confirm req to %1% representatives") % request_bundle_a.size ())); - } - - for (auto i (request_bundle_a.begin ()), n (request_bundle_a.end ()); i != n;) - { - std::vector> roots_hashes_l; - // Limit max request size hash + root to 7 pairs - while (roots_hashes_l.size () < confirm_req_hashes_max && !i->second.empty ()) - { - // expects ordering by priority, descending - roots_hashes_l.push_back (i->second.front ()); - i->second.pop_front (); - } - nano::confirm_req req{ node.network_params.network, roots_hashes_l }; - i->first->send (req); - if (i->second.empty ()) - { - i = request_bundle_a.erase (i); - } - else - { - ++i; - } - } - if (!request_bundle_a.empty ()) - { - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (delay_a), [node_w, request_bundle_a, callback_a, delay_a] () { - if (auto node_l = node_w.lock ()) - { - node_l->network.broadcast_confirm_req_batched_many (request_bundle_a, callback_a, delay_a, true); - } - }); - } - else if (callback_a) - { - callback_a (); - } -} - -void nano::network::broadcast_confirm_req_many (std::deque, std::shared_ptr>>>> requests_a, std::function callback_a, unsigned delay_a) -{ - auto pair_l (requests_a.front ()); - requests_a.pop_front (); - auto block_l (pair_l.first); - // confirm_req to representatives - auto endpoints (pair_l.second); - if (!endpoints->empty ()) - { - broadcast_confirm_req_base (block_l, endpoints, delay_a); - } - /* Continue while blocks remain - Broadcast with random delay between delay_a & 2*delay_a */ - if (!requests_a.empty ()) - { - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (delay_a + std::rand () % delay_a), [node_w, requests_a, callback_a, delay_a] () { - if (auto node_l = node_w.lock ()) - { - node_l->network.broadcast_confirm_req_many (requests_a, callback_a, delay_a); - } - }); - } - else if (callback_a) - { - callback_a (); - } -} - namespace { class network_message_visitor : public nano::message_visitor { public: network_message_visitor (nano::node & node_a, std::shared_ptr const & channel_a) : - node (node_a), - channel (channel_a) + node{ node_a }, + channel{ channel_a } { } void keepalive (nano::keepalive const & message_a) override { - if (node.config.logging.network_keepalive_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Received keepalive message from %1%") % channel->to_string ())); - } - - node.network.merge_peers (message_a.peers); - // Check for special node port data auto peer0 (message_a.peers[0]); if (peer0.address () == boost::asio::ip::address_v6{} && peer0.port () != 0) @@ -393,11 +255,6 @@ class network_message_visitor : public nano::message_visitor void publish (nano::publish const & message_a) override { - if (node.config.logging.network_message_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Publish message from %1% for %2%") % channel->to_string () % message_a.block->hash ().to_string ())); - } - if (!node.block_processor.full ()) { node.process_active (message_a.block); @@ -411,14 +268,6 @@ class network_message_visitor : public nano::message_visitor void confirm_req (nano::confirm_req const & message_a) override { - if (node.config.logging.network_message_logging ()) - { - if (!message_a.roots_hashes.empty ()) - { - node.logger.try_log (boost::str (boost::format ("Confirm_req message from %1% for hashes:roots %2%") % channel->to_string () % message_a.roots_string ())); - } - } - // Don't load nodes with disabled voting if (node.config.enable_voting && node.wallets.reps ().voting > 0) { @@ -431,11 +280,6 @@ class network_message_visitor : public nano::message_visitor void confirm_ack (nano::confirm_ack const & message_a) override { - if (node.config.logging.network_message_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Received confirm_ack message from %1% for %2% timestamp %3%") % channel->to_string () % message_a.vote->hashes_string () % std::to_string (message_a.vote->timestamp ()))); - } - if (!message_a.vote->account.is_zero ()) { node.vote_processor.vote (message_a.vote, channel); @@ -469,11 +313,6 @@ class network_message_visitor : public nano::message_visitor void telemetry_req (nano::telemetry_req const & message_a) override { - if (node.config.logging.network_telemetry_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Telemetry_req message from %1%") % channel->to_string ())); - } - // Send an empty telemetry_ack if we do not want, just to acknowledge that we have received the message to // remove any timeouts on the server side waiting for a message. nano::telemetry_ack telemetry_ack{ node.network_params.network }; @@ -487,11 +326,6 @@ class network_message_visitor : public nano::message_visitor void telemetry_ack (nano::telemetry_ack const & message_a) override { - if (node.config.logging.network_telemetry_logging ()) - { - node.logger.try_log (boost::str (boost::format ("Received telemetry_ack message from %1%") % channel->to_string ())); - } - node.telemetry.process (message_a, channel); } @@ -513,9 +347,10 @@ class network_message_visitor : public nano::message_visitor void nano::network::process_message (nano::message const & message, std::shared_ptr const & channel) { - node.stats.inc (nano::stat::type::message, nano::to_stat_detail (message.header.type), nano::stat::dir::in); + node.stats.inc (nano::stat::type::message, to_stat_detail (message.type ()), nano::stat::dir::in); + node.logger.trace (nano::log::type::network_processed, to_log_detail (message.type ()), nano::log::arg{ "message", message }); - network_message_visitor visitor (node, channel); + network_message_visitor visitor{ node, channel }; message.visit (visitor); } @@ -584,7 +419,7 @@ std::deque> nano::network::list_non_pr tcp_channels.list (result); nano::random_pool_shuffle (result.begin (), result.end ()); result.erase (std::remove_if (result.begin (), result.end (), [this] (std::shared_ptr const & channel) { - return this->node.rep_crawler.is_pr (*channel); + return node.rep_crawler.is_pr (channel); }), result.end ()); if (result.size () > count_a) @@ -998,23 +833,3 @@ std::unique_ptr nano::syn_cookies::collect_conta composite->add_component (std::make_unique (container_info{ "syn_cookies_per_ip", syn_cookies_per_ip_count, sizeof (decltype (cookies_per_ip)::value_type) })); return composite; } - -std::string nano::network::to_string (nano::networks network) -{ - switch (network) - { - case nano::networks::invalid: - return "invalid"; - case nano::networks::nano_beta_network: - return "beta"; - case nano::networks::nano_dev_network: - return "dev"; - case nano::networks::nano_live_network: - return "live"; - case nano::networks::nano_test_network: - return "test"; - // default case intentionally omitted to cause warnings for unhandled enums - } - - return "n/a"; -} diff --git a/nano/node/network.hpp b/nano/node/network.hpp index 56f6f23b86..cd5b90e047 100644 --- a/nano/node/network.hpp +++ b/nano/node/network.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -94,11 +95,7 @@ class network final void send_keepalive (std::shared_ptr const &); void send_keepalive_self (std::shared_ptr const &); void send_node_id_handshake (std::shared_ptr const &, std::optional const & cookie, std::optional const & respond_to); - void send_confirm_req (std::shared_ptr const & channel_a, std::pair const & hash_root_a); - void broadcast_confirm_req (std::shared_ptr const &); - void broadcast_confirm_req_base (std::shared_ptr const &, std::shared_ptr>> const &, unsigned, bool = false); - void broadcast_confirm_req_batched_many (std::unordered_map, std::deque>>, std::function = nullptr, unsigned = broadcast_interval_ms, bool = false); - void broadcast_confirm_req_many (std::deque, std::shared_ptr>>>>, std::function = nullptr, unsigned = broadcast_interval_ms); + void send_confirm_req (std::shared_ptr const & channel_a, std::pair const & hash_root_a); std::shared_ptr find_node_id (nano::account const &); std::shared_ptr find_channel (nano::endpoint const &); bool not_a_peer (nano::endpoint const &, bool); @@ -133,8 +130,6 @@ class network final std::optional prepare_handshake_query (nano::endpoint const & remote_endpoint); nano::node_id_handshake::response_payload prepare_handshake_response (nano::node_id_handshake::query_payload const & query, bool v2) const; - static std::string to_string (nano::networks); - private: void process_message (nano::message const &, std::shared_ptr const &); @@ -158,5 +153,6 @@ class network final static std::size_t const confirm_req_hashes_max = 7; static std::size_t const confirm_ack_hashes_max = 12; }; + std::unique_ptr collect_container_info (network & network, std::string const & name); } diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 2ec288a875..8397fa70d3 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include @@ -84,32 +86,19 @@ void nano::node::keepalive (std::string const & address_a, uint16_t port_a) } else { - node_l->logger.try_log (boost::str (boost::format ("Error resolving address: %1%:%2%: %3%") % address_a % port_a % ec.message ())); + node_l->logger.error (nano::log::type::node, "Error resolving address for keepalive: {}:{} ({})", address_a, port_a, ec.message ()); } }); } -std::unique_ptr nano::collect_container_info (rep_crawler & rep_crawler, std::string const & name) -{ - std::size_t count; - { - nano::lock_guard guard{ rep_crawler.active_mutex }; - count = rep_crawler.active.size (); - } - - auto const sizeof_element = sizeof (decltype (rep_crawler.active)::value_type); - auto composite = std::make_unique (name); - composite->add_component (std::make_unique (container_info{ "active", count, sizeof_element })); - return composite; -} - -nano::keypair nano::load_or_create_node_id (std::filesystem::path const & application_path, nano::logger_mt & logger) +nano::keypair nano::load_or_create_node_id (std::filesystem::path const & application_path) { auto node_private_key_path = application_path / "node_id_private.key"; std::ifstream ifs (node_private_key_path.c_str ()); if (ifs.good ()) { - logger.always_log (boost::str (boost::format ("%1% exists, reading node id from it") % node_private_key_path.string ())); + nano::default_logger ().info (nano::log::type::init, "Reading node id from: '{}'", node_private_key_path.string ()); + std::string node_private_key; ifs >> node_private_key; release_assert (node_private_key.size () == 64); @@ -119,7 +108,8 @@ nano::keypair nano::load_or_create_node_id (std::filesystem::path const & applic else { // no node_id found, generate new one - logger.always_log (boost::str (boost::format ("%1% does not exist, creating a new node_id") % node_private_key_path.string ())); + nano::default_logger ().info (nano::log::type::init, "Generating a new node id, saving to: '{}'", node_private_key_path.string ()); + nano::keypair kp; std::ofstream ofs (node_private_key_path.c_str (), std::ofstream::out | std::ofstream::trunc); ofs << kp.prv.to_string () << std::endl @@ -130,31 +120,32 @@ nano::keypair nano::load_or_create_node_id (std::filesystem::path const & applic } } -nano::node::node (boost::asio::io_context & io_ctx_a, uint16_t peering_port_a, std::filesystem::path const & application_path_a, nano::logging const & logging_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) : - node (io_ctx_a, application_path_a, nano::node_config (peering_port_a, logging_a), work_a, flags_a, seq) +nano::node::node (boost::asio::io_context & io_ctx_a, uint16_t peering_port_a, std::filesystem::path const & application_path_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) : + node (io_ctx_a, application_path_a, nano::node_config (peering_port_a), work_a, flags_a, seq) { } nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path const & application_path_a, nano::node_config const & config_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) : + node_id{ load_or_create_node_id (application_path_a) }, write_database_queue (!flags_a.force_use_write_database_queue && (config_a.rocksdb_config.enable)), io_ctx (io_ctx_a), node_initialized_latch (1), config (config_a), network_params{ config.network_params }, + logger{ make_logger_identifier (node_id) }, stats (config.stats_config), workers{ config.background_threads, nano::thread_role::name::worker }, bootstrap_workers{ config.bootstrap_serving_threads, nano::thread_role::name::bootstrap_worker }, flags (flags_a), work (work_a), distributed_work (*this), - logger (config_a.logging.min_time_between_log_output), store_impl (nano::make_store (logger, application_path_a, network_params.ledger, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade)), store (*store_impl), - unchecked{ stats, flags.disable_block_processor_unchecked_deletion }, + unchecked{ config.max_unchecked_blocks, stats, flags.disable_block_processor_unchecked_deletion }, wallets_store_impl (std::make_unique (application_path_a / "wallets.ldb", config_a.lmdb_config)), wallets_store (*wallets_store_impl), - gap_cache (*this), - ledger (store, stats, network_params.ledger, flags_a.generate_cache), + ledger_impl{ std::make_unique (store, stats, network_params.ledger, flags_a.generate_cache) }, + ledger{ *ledger_impl }, outbound_limiter{ outbound_bandwidth_limiter_config (config) }, // empty `config.peering_port` means the user made no port choice at all; // otherwise, any value is considered, with `0` having the special meaning of 'let the OS pick a port instead' @@ -173,18 +164,19 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons tcp_listener{ std::make_shared (network.port, *this, config.tcp_incoming_connections_max) }, application_path (application_path_a), port_mapping (*this), - rep_crawler (*this), - vote_processor (active, observers, stats, config, flags, logger, online_reps, rep_crawler, ledger, network_params), + rep_crawler (config.rep_crawler, *this), + rep_tiers{ ledger, network_params, online_reps, stats, logger }, + vote_processor{ active, observers, stats, config, flags, logger, online_reps, rep_crawler, ledger, network_params, rep_tiers }, warmed_up (0), block_processor (*this, write_database_queue), online_reps (ledger, config), history{ config.network_params.voting }, vote_uniquer{}, - confirmation_height_processor (ledger, write_database_queue, config.conf_height_processor_batch_min_time, config.logging, logger, node_initialized_latch, flags.confirmation_height_processor_mode), + confirmation_height_processor (ledger, write_database_queue, config.conf_height_processor_batch_min_time, logger, node_initialized_latch, flags.confirmation_height_processor_mode), vote_cache{ config.vote_cache, stats }, - generator{ config, ledger, wallets, vote_processor, history, network, stats, /* non-final */ false }, - final_generator{ config, ledger, wallets, vote_processor, history, network, stats, /* final */ true }, - active (*this, confirmation_height_processor), + generator{ config, ledger, wallets, vote_processor, history, network, stats, logger, /* non-final */ false }, + final_generator{ config, ledger, wallets, vote_processor, history, network, stats, logger, /* final */ true }, + active{ *this, confirmation_height_processor, block_processor }, scheduler_impl{ std::make_unique (*this) }, scheduler{ *scheduler_impl }, aggregator (config, stats, generator, final_generator, history, ledger, wallets, active), @@ -193,19 +185,17 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons ascendboot{ config, block_processor, ledger, network, stats }, websocket{ config.websocket_config, observers, wallets, ledger, io_ctx, logger }, epoch_upgrader{ *this, ledger, store, network_params, logger }, + local_block_broadcaster{ *this, block_processor, network, stats, !flags.disable_block_processor_republishing }, + process_live_dispatcher{ ledger, scheduler.priority, vote_cache, websocket }, startup_time (std::chrono::steady_clock::now ()), - node_seq (seq), - block_broadcast{ network, block_arrival, !flags.disable_block_processor_republishing }, - block_publisher{ active }, - gap_tracker{ gap_cache }, - process_live_dispatcher{ ledger, scheduler.priority, vote_cache, websocket } -{ - block_broadcast.connect (block_processor); - block_publisher.connect (block_processor); - gap_tracker.connect (block_processor); + node_seq (seq) +{ + logger.debug (nano::log::type::node, "Constructing node..."); + process_live_dispatcher.connect (block_processor); + unchecked.satisfied.add ([this] (nano::unchecked_info const & info) { - this->block_processor.add (info.block); + block_processor.add (info.block, nano::block_source::unchecked); }); vote_cache.rep_weight_query = [this] (nano::account const & rep) { @@ -240,7 +230,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons { observers.blocks.add ([this] (nano::election_status const & status_a, std::vector const & votes_a, nano::account const & account_a, nano::amount const & amount_a, bool is_state_send_a, bool is_state_epoch_a) { auto block_a (status_a.winner); - if ((status_a.type == nano::election_status_type::active_confirmed_quorum || status_a.type == nano::election_status_type::active_confirmation_height) && this->block_arrival.recent (block_a->hash ())) + if ((status_a.type == nano::election_status_type::active_confirmed_quorum || status_a.type == nano::election_status_type::active_confirmation_height)) { auto node_l (shared_from_this ()); background ([node_l, block_a, account_a, amount_a, is_state_send_a, is_state_epoch_a] () { @@ -259,13 +249,13 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons // Subtype field else if (block_a->type () == nano::block_type::state) { - if (block_a->link ().is_zero ()) + if (block_a->is_change ()) { event.add ("subtype", "change"); } else if (is_state_epoch_a) { - debug_assert (amount_a == 0 && node_l->ledger.is_epoch_link (block_a->link ())); + debug_assert (amount_a == 0 && node_l->ledger.is_epoch_link (block_a->link_field ().value ())); event.add ("subtype", "epoch"); } else @@ -288,10 +278,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons } else { - if (node_l->config.logging.callback_logging ()) - { - node_l->logger.always_log (boost::str (boost::format ("Error resolving callback: %1%:%2%: %3%") % address % port % ec.message ())); - } + node_l->logger.error (nano::log::type::rpc_callbacks, "Error resolving callback: {}:{} ({})", address, port, ec.message ()); node_l->stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } }); @@ -321,15 +308,15 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons observers.endpoint.add ([this] (std::shared_ptr const & channel_a) { this->network.send_keepalive_self (channel_a); }); - observers.vote.add ([this] (std::shared_ptr vote_a, std::shared_ptr const & channel_a, nano::vote_code code_a) { - debug_assert (code_a != nano::vote_code::invalid); - auto active_in_rep_crawler (!this->rep_crawler.response (channel_a, vote_a)); + + observers.vote.add ([this] (std::shared_ptr vote, std::shared_ptr const & channel, nano::vote_code code) { + debug_assert (code != nano::vote_code::invalid); + bool active_in_rep_crawler = rep_crawler.process (vote, channel); if (active_in_rep_crawler) { // Representative is defined as online if replying to live votes or rep_crawler queries - this->online_reps.observe (vote_a->account); + online_reps.observe (vote->account); } - this->gap_cache.vote (vote_a); }); // Cancelling local work generation @@ -338,26 +325,25 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons this->distributed_work.cancel (root_a); }); - logger.always_log ("Node starting, version: ", NANO_VERSION_STRING); - logger.always_log ("Build information: ", BUILD_INFO); - logger.always_log ("Database backend: ", store.vendor_get ()); - auto const network_label = network_params.network.get_current_network_as_string (); - logger.always_log ("Active network: ", network_label); - logger.always_log (boost::str (boost::format ("Work pool running %1% threads %2%") % work.threads.size () % (work.opencl ? "(1 for OpenCL)" : ""))); - logger.always_log (boost::str (boost::format ("%1% work peers configured") % config.work_peers.size ())); - if (!work_generation_enabled ()) - { - logger.always_log ("Work generation is disabled"); - } + logger.info (nano::log::type::node, "Node starting, version: {}", NANO_VERSION_STRING); + logger.info (nano::log::type::node, "Build information: {}", BUILD_INFO); + logger.info (nano::log::type::node, "Active network: {}", network_label); + logger.info (nano::log::type::node, "Database backend: {}", store.vendor_get ()); + logger.info (nano::log::type::node, "Data path: {}", application_path.string ()); + logger.info (nano::log::type::node, "Work pool threads: {} ({})", work.threads.size (), (work.opencl ? "OpenCL" : "CPU")); + logger.info (nano::log::type::node, "Work peers: {}", config.work_peers.size ()); + logger.info (nano::log::type::node, "Node ID: {}", node_id.pub.to_node_id ()); - if (config.logging.node_lifetime_tracing ()) + if (!work_generation_enabled ()) { - logger.always_log ("Constructing node"); + logger.info (nano::log::type::node, "Work generation is disabled"); } - logger.always_log (boost::str (boost::format ("Outbound Voting Bandwidth limited to %1% bytes per second, burst ratio %2%") % config.bandwidth_limit % config.bandwidth_limit_burst_ratio)); + logger.info (nano::log::type::node, "Outbound bandwidth limit: {} bytes/s, burst ratio: {}", + config.bandwidth_limit, + config.bandwidth_limit_burst_ratio); // First do a pass with a read to see if any writing needs doing, this saves needing to open a write lock (and potentially blocking) auto is_initialized (false); @@ -375,59 +361,62 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons if (!ledger.block_or_pruned_exists (config.network_params.ledger.genesis->hash ())) { - std::stringstream ss; - ss << "Genesis block not found. This commonly indicates a configuration issue, check that the --network or --data_path command line arguments are correct, " - "and also the ledger backend node config option. If using a read-only CLI command a ledger must already exist, start the node with --daemon first."; + logger.critical (nano::log::type::node, "Genesis block not found. This commonly indicates a configuration issue, check that the --network or --data_path command line arguments are correct, and also the ledger backend node config option. If using a read-only CLI command a ledger must already exist, start the node with --daemon first."); + if (network_params.network.is_beta_network ()) { - ss << " Beta network may have reset, try clearing database files"; + logger.critical (nano::log::type::node, "Beta network may have reset, try clearing database files"); } - auto const str = ss.str (); - logger.always_log (str); - std::cerr << str << std::endl; std::exit (1); } if (config.enable_voting) { - std::ostringstream stream; - stream << "Voting is enabled, more system resources will be used"; - auto voting (wallets.reps ().voting); - if (voting > 0) + auto reps = wallets.reps (); + logger.info (nano::log::type::node, "Voting is enabled, more system resources will be used, local representatives: {}", reps.accounts.size ()); + for (auto const & account : reps.accounts) { - stream << ". " << voting << " representative(s) are configured"; - if (voting > 1) - { - stream << ". Voting with more than one representative can limit performance"; - } + logger.info (nano::log::type::node, "Local representative: {}", account.to_account ()); + } + if (reps.accounts.size () > 1) + { + logger.warn (nano::log::type::node, "Voting with more than one representative can limit performance"); } - logger.always_log (stream.str ()); } - node_id = nano::load_or_create_node_id (application_path, logger); - logger.always_log ("Node ID: ", node_id.pub.to_node_id ()); - if ((network_params.network.is_live_network () || network_params.network.is_beta_network ()) && !flags.inactive_node) { auto const bootstrap_weights = get_bootstrap_weights (); + ledger.bootstrap_weight_max_blocks = bootstrap_weights.first; + + logger.info (nano::log::type::node, "Initial bootstrap height: {}", ledger.bootstrap_weight_max_blocks); + logger.info (nano::log::type::node, "Current ledger height: {}", ledger.cache.block_count.load ()); + // Use bootstrap weights if initial bootstrap is not completed const bool use_bootstrap_weight = ledger.cache.block_count < bootstrap_weights.first; if (use_bootstrap_weight) { + logger.info (nano::log::type::node, "Using predefined representative weights, since block count is less than bootstrap threshold"); + ledger.bootstrap_weights = bootstrap_weights.second; - for (auto const & rep : ledger.bootstrap_weights) + + logger.info (nano::log::type::node, "************************************ Bootstrap weights ************************************"); + + // Sort the weights + std::vector> sorted_weights (ledger.bootstrap_weights.begin (), ledger.bootstrap_weights.end ()); + std::sort (sorted_weights.begin (), sorted_weights.end (), [] (auto const & entry1, auto const & entry2) { + return entry1.second > entry2.second; + }); + + for (auto const & rep : sorted_weights) { - logger.always_log ("Using bootstrap rep weight: ", rep.first.to_account (), " -> ", nano::uint128_union (rep.second).format_balance (Mxrb_ratio, 0, true), " XRB"); + logger.info (nano::log::type::node, "Using bootstrap rep weight: {} -> {}", + rep.first.to_account (), + nano::uint128_union (rep.second).format_balance (Mxrb_ratio, 0, true)); } - } - ledger.bootstrap_weight_max_blocks = bootstrap_weights.first; - // Drop unchecked blocks if initial bootstrap is completed - if (!flags.disable_unchecked_drop && !use_bootstrap_weight && !flags.read_only) - { - unchecked.clear (); - logger.always_log ("Dropping unchecked blocks"); + logger.info (nano::log::type::node, "************************************ ================= ************************************"); } } @@ -437,16 +426,12 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons { if (config.enable_voting && !flags.inactive_node) { - std::string str = "Incompatibility detected between config node.enable_voting and existing pruned blocks"; - logger.always_log (str); - std::cerr << str << std::endl; + logger.critical (nano::log::type::node, "Incompatibility detected between config node.enable_voting and existing pruned blocks"); std::exit (1); } else if (!flags.enable_pruning && !flags.inactive_node) { - std::string str = "To start node with existing pruned blocks use launch flag --enable_pruning"; - logger.always_log (str); - std::cerr << str << std::endl; + logger.critical (nano::log::type::node, "To start node with existing pruned blocks use launch flag --enable_pruning"); std::exit (1); } } @@ -456,13 +441,11 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons nano::node::~node () { - if (config.logging.node_lifetime_tracing ()) - { - logger.always_log ("Destructing node"); - } + logger.debug (nano::log::type::node, "Destructing node..."); stop (); } +// TODO: Move to a separate class void nano::node::do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const & address, uint16_t port, std::shared_ptr const & target, std::shared_ptr const & body, std::shared_ptr const & resolver) { if (i_a != boost::asio::ip::tcp::resolver::iterator{}) @@ -494,41 +477,30 @@ void nano::node::do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, } else { - if (node_l->config.logging.callback_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Callback to %1%:%2% failed with status: %3%") % address % port % resp->result ())); - } + node_l->logger.error (nano::log::type::rpc_callbacks, "Callback to {}:{} failed [status: {}]", address, port, nano::util::to_str (resp->result ())); node_l->stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } } else { - if (node_l->config.logging.callback_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Unable complete callback: %1%:%2%: %3%") % address % port % ec.message ())); - } + node_l->logger.error (nano::log::type::rpc_callbacks, "Unable to complete callback: {}:{} ({})", address, port, ec.message ()); node_l->stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); }; }); } else { - if (node_l->config.logging.callback_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Unable to send callback: %1%:%2%: %3%") % address % port % ec.message ())); - } + node_l->logger.error (nano::log::type::rpc_callbacks, "Unable to send callback: {}:{} ({})", address, port, ec.message ()); node_l->stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } }); } else { - if (node_l->config.logging.callback_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Unable to connect to callback address: %1%:%2%: %3%") % address % port % ec.message ())); - } + node_l->logger.error (nano::log::type::rpc_callbacks, "Unable to connect to callback address: {}:{} ({})", address, port, ec.message ()); node_l->stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); ++i_a; + node_l->do_rpc_callback (i_a, address, port, target, body, resolver); } }); @@ -544,7 +516,6 @@ std::unique_ptr nano::collect_container_info (no { auto composite = std::make_unique (name); composite->add_component (collect_container_info (node.work, "work")); - composite->add_component (collect_container_info (node.gap_cache, "gap_cache")); composite->add_component (collect_container_info (node.ledger, "ledger")); composite->add_component (collect_container_info (node.active, "active")); composite->add_component (collect_container_info (node.bootstrap_initiator, "bootstrap_initiator")); @@ -555,9 +526,8 @@ std::unique_ptr nano::collect_container_info (no composite->add_component (collect_container_info (node.observers, "observers")); composite->add_component (collect_container_info (node.wallets, "wallets")); composite->add_component (collect_container_info (node.vote_processor, "vote_processor")); - composite->add_component (collect_container_info (node.rep_crawler, "rep_crawler")); - composite->add_component (collect_container_info (node.block_processor, "block_processor")); - composite->add_component (collect_container_info (node.block_arrival, "block_arrival")); + composite->add_component (node.rep_crawler.collect_container_info ("rep_crawler")); + composite->add_component (node.block_processor.collect_container_info ("block_processor")); composite->add_component (collect_container_info (node.online_reps, "online_reps")); composite->add_component (collect_container_info (node.history, "history")); composite->add_component (node.block_uniquer.collect_container_info ("block_uniquer")); @@ -571,40 +541,35 @@ std::unique_ptr nano::collect_container_info (no composite->add_component (collect_container_info (node.final_generator, "vote_generator_final")); composite->add_component (node.ascendboot.collect_container_info ("bootstrap_ascending")); composite->add_component (node.unchecked.collect_container_info ("unchecked")); + composite->add_component (node.local_block_broadcaster.collect_container_info ("local_block_broadcaster")); + composite->add_component (node.rep_tiers.collect_container_info ("rep_tiers")); return composite; } void nano::node::process_active (std::shared_ptr const & incoming) { - block_arrival.add (incoming->hash ()); block_processor.add (incoming); } -[[nodiscard]] nano::process_return nano::node::process (store::write_transaction const & transaction, nano::block & block) +[[nodiscard]] nano::block_status nano::node::process (store::write_transaction const & transaction, std::shared_ptr block) { return ledger.process (transaction, block); } -nano::process_return nano::node::process (nano::block & block) +nano::block_status nano::node::process (std::shared_ptr block) { auto const transaction = store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending }); return process (transaction, block); } -std::optional nano::node::process_local (std::shared_ptr const & block_a) +std::optional nano::node::process_local (std::shared_ptr const & block_a) { - // Add block hash as recently arrived to trigger automatic rebroadcast and election - block_arrival.add (block_a->hash ()); - block_broadcast.set_local (block_a); - return block_processor.add_blocking (block_a); + return block_processor.add_blocking (block_a, nano::block_source::local); } void nano::node::process_local_async (std::shared_ptr const & block_a) { - // Add block hash as recently arrived to trigger automatic rebroadcast and election - block_arrival.add (block_a->hash ()); - // Set current time to trigger automatic rebroadcast and election - block_processor.add (block_a); + block_processor.add (block_a, nano::block_source::local); } void nano::node::start () @@ -616,13 +581,6 @@ void nano::node::start () { ongoing_bootstrap (); } - if (!flags.disable_unchecked_cleanup) - { - auto this_l (shared ()); - workers.push_task ([this_l] () { - this_l->ongoing_unchecked_cleanup (); - }); - } if (flags.enable_pruning) { auto this_l (shared ()); @@ -634,7 +592,6 @@ void nano::node::start () { rep_crawler.start (); } - ongoing_rep_calculation (); ongoing_peer_store (); ongoing_online_weight_calculation_queue (); @@ -655,7 +612,7 @@ void nano::node::start () network.port = tcp_listener->endpoint ().port (); } - logger.always_log (boost::str (boost::format ("Node started with peering port `%1%`.") % network.port)); + logger.info (nano::log::type::node, "Node peering port: {}", network.port.load ()); } if (!flags.disable_backup) @@ -680,6 +637,9 @@ void nano::node::start () port_mapping.start (); } wallets.start (); + rep_tiers.start (); + vote_processor.start (); + block_processor.start (); active.start (); generator.start (); final_generator.start (); @@ -692,6 +652,7 @@ void nano::node::start () } websocket.start (); telemetry.start (); + local_block_broadcaster.start (); } void nano::node::stop () @@ -702,7 +663,7 @@ void nano::node::stop () return; } - logger.always_log ("Node stopping"); + logger.info (nano::log::type::node, "Node stopping..."); // Cancels ongoing work generation tasks, which may be blocking other threads // No tasks may wait for work generation in I/O threads, or termination signal capturing will be unable to call node::stop() @@ -712,10 +673,12 @@ void nano::node::stop () { ascendboot.stop (); } + rep_crawler.stop (); unchecked.stop (); block_processor.stop (); aggregator.stop (); vote_processor.stop (); + rep_tiers.stop (); scheduler.stop (); active.stop (); generator.stop (); @@ -732,17 +695,18 @@ void nano::node::stop () stats.stop (); epoch_upgrader.stop (); workers.stop (); + local_block_broadcaster.stop (); // work pool is not stopped on purpose due to testing setup } -void nano::node::keepalive_preconfigured (std::vector const & peers_a) +void nano::node::keepalive_preconfigured () { - for (auto i (peers_a.begin ()), n (peers_a.end ()); i != n; ++i) + for (auto const & peer : config.preconfigured_peers) { // can't use `network.port` here because preconfigured peers are referenced // just by their address, so we rely on them listening on the default port // - keepalive (*i, network_params.network.default_node_port); + keepalive (peer, network_params.network.default_node_port); } } @@ -760,8 +724,7 @@ nano::uint128_t nano::node::balance (nano::account const & account_a) std::shared_ptr nano::node::block (nano::block_hash const & hash_a) { - auto const transaction (store.tx_begin_read ()); - return store.block.get (transaction, hash_a); + return ledger.block (store.tx_begin_read (), hash_a); } std::pair nano::node::balance_pending (nano::account const & account_a, bool only_confirmed_a) @@ -778,18 +741,6 @@ nano::uint128_t nano::node::weight (nano::account const & account_a) return ledger.weight (account_a); } -nano::block_hash nano::node::rep_block (nano::account const & account_a) -{ - auto const transaction (store.tx_begin_read ()); - nano::block_hash result (0); - auto info = ledger.account_info (transaction, account_a); - if (info) - { - result = ledger.representative (transaction, info->head); - } - return result; -} - nano::uint128_t nano::node::minimum_principal_weight () { return online_reps.trended () / network_params.network.principal_weight_factor; @@ -811,23 +762,10 @@ void nano::node::long_inactivity_cleanup () { store.online_weight.clear (transaction); store.peer.clear (transaction); - logger.always_log ("Removed records of peers and online weight after a long period of inactivity"); + logger.info (nano::log::type::node, "Removed records of peers and online weight after a long period of inactivity"); } } -void nano::node::ongoing_rep_calculation () -{ - auto now (std::chrono::steady_clock::now ()); - vote_processor.calculate_weights (); - std::weak_ptr node_w (shared_from_this ()); - workers.add_timed_task (now + std::chrono::minutes (10), [node_w] () { - if (auto node_l = node_w.lock ()) - { - node_l->ongoing_rep_calculation (); - } - }); -} - void nano::node::ongoing_bootstrap () { auto next_wakeup = network_params.network.bootstrap_interval; @@ -953,56 +891,6 @@ void nano::node::bootstrap_wallet () } } -void nano::node::unchecked_cleanup () -{ - std::vector digests; - std::deque cleaning_list; - auto const attempt (bootstrap_initiator.current_attempt ()); - const bool long_attempt (attempt != nullptr && std::chrono::duration_cast (std::chrono::steady_clock::now () - attempt->attempt_start).count () > config.unchecked_cutoff_time.count ()); - // Collect old unchecked keys - if (ledger.cache.block_count >= ledger.bootstrap_weight_max_blocks && !long_attempt) - { - auto const now (nano::seconds_since_epoch ()); - auto const transaction (store.tx_begin_read ()); - // Max 1M records to clean, max 2 minutes reading to prevent slow i/o systems issues - unchecked.for_each ( - [this, &digests, &cleaning_list, &now] (nano::unchecked_key const & key, nano::unchecked_info const & info) { - if ((now - info.modified ()) > static_cast (config.unchecked_cutoff_time.count ())) - { - digests.push_back (network.publish_filter.hash (info.block)); - cleaning_list.push_back (key); - } }, [iterations = 0, count = 1024 * 1024] () mutable { return iterations++ < count; }); - } - if (!cleaning_list.empty ()) - { - logger.always_log (boost::str (boost::format ("Deleting %1% old unchecked blocks") % cleaning_list.size ())); - } - // Delete old unchecked keys in batches - while (!cleaning_list.empty ()) - { - std::size_t deleted_count (0); - while (deleted_count++ < 2 * 1024 && !cleaning_list.empty ()) - { - auto key (cleaning_list.front ()); - cleaning_list.pop_front (); - if (unchecked.exists (key)) - { - unchecked.del (key); - } - } - } - // Delete from the duplicate filter - network.publish_filter.clear (digests); -} - -void nano::node::ongoing_unchecked_cleanup () -{ - unchecked_cleanup (); - workers.add_timed_task (std::chrono::steady_clock::now () + network_params.node.unchecked_cleaning_interval, [this_l = shared ()] () { - this_l->ongoing_unchecked_cleanup (); - }); -} - bool nano::node::collect_ledger_pruning_targets (std::deque & pruning_targets_a, nano::account & last_account_a, uint64_t const batch_read_size_a, uint64_t const max_depth_a, uint64_t const cutoff_time_a) { uint64_t read_operations (0); @@ -1016,7 +904,7 @@ bool nano::node::collect_ledger_pruning_targets (std::deque & uint64_t depth (0); while (!hash.is_zero () && depth < max_depth_a) { - auto block (store.block.get (transaction, hash)); + auto block = ledger.block (transaction, hash); if (block != nullptr) { if (block->sideband ().timestamp > cutoff_time_a || depth == 0) @@ -1056,7 +944,7 @@ bool nano::node::collect_ledger_pruning_targets (std::deque & return !finish_transaction || last_account_a.is_zero (); } -void nano::node::ledger_pruning (uint64_t const batch_size_a, bool bootstrap_weight_reached_a, bool log_to_cout_a) +void nano::node::ledger_pruning (uint64_t const batch_size_a, bool bootstrap_weight_reached_a) { uint64_t const max_depth (config.max_pruning_depth != 0 ? config.max_pruning_depth : std::numeric_limits::max ()); uint64_t const cutoff_time (bootstrap_weight_reached_a ? nano::seconds_since_epoch () - config.max_pruning_age.count () : std::numeric_limits::max ()); @@ -1086,32 +974,18 @@ void nano::node::ledger_pruning (uint64_t const batch_size_a, bool bootstrap_wei pruning_targets.pop_front (); } pruned_count += transaction_write_count; - auto log_message (boost::str (boost::format ("%1% blocks pruned") % pruned_count)); - if (!log_to_cout_a) - { - logger.try_log (log_message); - } - else - { - std::cout << log_message << std::endl; - } + + logger.debug (nano::log::type::prunning, "Pruned blocks: {}", pruned_count); } } - auto const log_message (boost::str (boost::format ("Total recently pruned block count: %1%") % pruned_count)); - if (!log_to_cout_a) - { - logger.always_log (log_message); - } - else - { - std::cout << log_message << std::endl; - } + + logger.debug (nano::log::type::prunning, "Total recently pruned block count: {}", pruned_count); } void nano::node::ongoing_ledger_pruning () { auto bootstrap_weight_reached (ledger.cache.block_count >= ledger.bootstrap_weight_max_blocks); - ledger_pruning (flags.block_processor_batch_size != 0 ? flags.block_processor_batch_size : 2 * 1024, bootstrap_weight_reached, false); + ledger_pruning (flags.block_processor_batch_size != 0 ? flags.block_processor_batch_size : 2 * 1024, bootstrap_weight_reached); auto const ledger_pruning_interval (bootstrap_weight_reached ? config.max_pruning_age : std::min (config.max_pruning_age, std::chrono::seconds (15 * 60))); auto this_l (shared ()); workers.add_timed_task (std::chrono::steady_clock::now () + ledger_pruning_interval, [this_l] () { @@ -1185,50 +1059,50 @@ bool nano::node::work_generation_enabled (std::vector nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a) +std::optional nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a) { - auto opt_work_l (work_generate_blocking (block_a.work_version (), block_a.root (), difficulty_a, block_a.account ())); - if (opt_work_l.is_initialized ()) + auto opt_work_l (work_generate_blocking (block_a.work_version (), block_a.root (), difficulty_a, block_a.account_field ())); + if (opt_work_l.has_value ()) { - block_a.block_work_set (*opt_work_l); + block_a.block_work_set (opt_work_l.value ()); } return opt_work_l; } -void nano::node::work_generate (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::function)> callback_a, boost::optional const & account_a, bool secondary_work_peers_a) +void nano::node::work_generate (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::function)> callback_a, std::optional const & account_a, bool secondary_work_peers_a) { auto const & peers_l (secondary_work_peers_a ? config.secondary_work_peers : config.work_peers); if (distributed_work.make (version_a, root_a, peers_l, difficulty_a, callback_a, account_a)) { // Error in creating the job (either stopped or work generation is not possible) - callback_a (boost::none); + callback_a (std::nullopt); } } -boost::optional nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, boost::optional const & account_a) +std::optional nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::optional const & account_a) { - std::promise> promise; + std::promise> promise; work_generate ( - version_a, root_a, difficulty_a, [&promise] (boost::optional opt_work_a) { + version_a, root_a, difficulty_a, [&promise] (std::optional opt_work_a) { promise.set_value (opt_work_a); }, account_a); return promise.get_future ().get (); } -boost::optional nano::node::work_generate_blocking (nano::block & block_a) +std::optional nano::node::work_generate_blocking (nano::block & block_a) { debug_assert (network_params.network.is_dev_network ()); return work_generate_blocking (block_a, default_difficulty (nano::work_version::work_1)); } -boost::optional nano::node::work_generate_blocking (nano::root const & root_a) +std::optional nano::node::work_generate_blocking (nano::root const & root_a) { debug_assert (network_params.network.is_dev_network ()); return work_generate_blocking (root_a, default_difficulty (nano::work_version::work_1)); } -boost::optional nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a) +std::optional nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a) { debug_assert (network_params.network.is_dev_network ()); return work_generate_blocking (nano::work_version::work_1, root_a, difficulty_a); @@ -1238,7 +1112,7 @@ void nano::node::add_initial_peers () { if (flags.disable_add_initial_peers) { - logger.always_log ("Skipping add_initial_peers because disable_add_initial_peers is set"); + logger.warn (nano::log::type::node, "Not adding initial peers because `disable_add_initial_peers` flag is set"); return; } @@ -1318,12 +1192,12 @@ void nano::node::receive_confirmed (store::transaction const & block_transaction { if (!ledger.block_or_pruned_exists (block_transaction_a, hash_a)) { - logger.try_log (boost::str (boost::format ("Confirmed block is missing: %1%") % hash_a.to_string ())); - debug_assert (false && "Confirmed block is missing"); + logger.warn (nano::log::type::node, "Confirmed block is missing: {}", hash_a.to_string ()); + debug_assert (false, "Confirmed block is missing"); } else { - logger.try_log (boost::str (boost::format ("Block %1% has already been received") % hash_a.to_string ())); + logger.warn (nano::log::type::node, "Block has already been received: {}", hash_a.to_string ()); } } } @@ -1334,20 +1208,15 @@ void nano::node::process_confirmed_data (store::transaction const & transaction_ { // Faster account calculation account_a = block_a->account (); - if (account_a.is_zero ()) - { - account_a = block_a->sideband ().account; - } // Faster amount calculation auto previous (block_a->previous ()); - bool error (false); - auto previous_balance (ledger.balance_safe (transaction_a, previous, error)); - auto block_balance = ledger.balance (*block_a); + auto previous_balance = ledger.balance (transaction_a, previous); + auto block_balance = block_a->balance (); if (hash_a != ledger.constants.genesis->account ()) { - if (!error) + if (previous_balance) { - amount_a = block_balance > previous_balance ? block_balance - previous_balance : previous_balance - block_balance; + amount_a = block_balance > previous_balance.value () ? block_balance.number () - previous_balance.value () : previous_balance.value () - block_balance.number (); } else { @@ -1364,7 +1233,7 @@ void nano::node::process_confirmed_data (store::transaction const & transaction_ { is_state_send_a = true; } - if (amount_a == 0 && network_params.ledger.epochs.is_epoch_link (state->link ())) + if (amount_a == 0 && network_params.ledger.epochs.is_epoch_link (state->link_field ().value ())) { is_state_epoch_a = true; } @@ -1380,8 +1249,10 @@ void nano::node::process_confirmed (nano::election_status const & status_a, uint { auto hash (status_a.winner->hash ()); decltype (iteration_a) const num_iters = (config.block_processor_batch_max_time / network_params.node.process_confirmed_interval) * 4; - if (auto block_l = ledger.store.block.get (ledger.store.tx_begin_read (), hash)) + if (auto block_l = ledger.block (ledger.store.tx_begin_read (), hash)) { + logger.trace (nano::log::type::node, nano::log::detail::process_confirmed, nano::log::arg{ "block", block_l }); + confirmation_height_processor.add (block_l); } else if (iteration_a < num_iters) @@ -1418,7 +1289,7 @@ bool nano::node::init_error () const return store.init_error () || wallets_store.init_error (); } -std::pair nano::node::get_bootstrap_weights () const +std::pair> nano::node::get_bootstrap_weights () const { std::unordered_map weights; uint8_t const * weight_buffer = network_params.network.is_live_network () ? nano_bootstrap_weights_live : nano_bootstrap_weights_beta; @@ -1453,7 +1324,7 @@ void nano::node::bootstrap_block (const nano::block_hash & hash) if (!ledger.pruning || !store.pruned.exists (store.tx_begin_read (), hash)) { // We don't have the block, try to bootstrap it - gap_cache.bootstrap_start (hash); + // TODO: Use ascending bootstraper to bootstrap block hash } } @@ -1495,6 +1366,12 @@ nano::telemetry_data nano::node::local_telemetry () const return telemetry_data; } +std::string nano::node::make_logger_identifier (const nano::keypair & node_id) +{ + // Node identifier consists of first 10 characters of node id + return node_id.pub.to_node_id ().substr (0, 10); +} + /* * node_wrapper */ @@ -1504,13 +1381,14 @@ nano::node_wrapper::node_wrapper (std::filesystem::path const & path_a, std::fil io_context (std::make_shared ()), work{ network_params.network, 1 } { - boost::system::error_code error_chmod; - /* * @warning May throw a filesystem exception */ std::filesystem::create_directories (path_a); + + boost::system::error_code error_chmod; nano::set_secure_perm_directory (path_a, error_chmod); + nano::daemon_config daemon_config{ path_a, network_params }; auto error = nano::read_node_config_toml (config_path_a, daemon_config, node_flags_a.config_overrides); if (error) @@ -1527,8 +1405,6 @@ nano::node_wrapper::node_wrapper (std::filesystem::path const & path_a, std::fil auto & node_config = daemon_config.node; node_config.peering_port = 24000; - node_config.logging.max_size = std::numeric_limits::max (); - node_config.logging.init (path_a); node = std::make_shared (*io_context, path_a, node_config, work, node_flags_a); } diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 4e7b567444..65ad016ab1 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -1,15 +1,14 @@ #pragma once +#include #include +#include #include #include #include #include #include #include -#include -#include -#include #include #include #include @@ -19,14 +18,14 @@ #include #include #include -#include -#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -37,7 +36,6 @@ #include #include #include -#include #include #include @@ -45,6 +43,7 @@ #include #include +#include #include namespace nano @@ -60,8 +59,6 @@ namespace scheduler class component; } -std::unique_ptr collect_container_info (rep_crawler & rep_crawler, std::string const & name); - // Configs backlog_population::config backlog_population_config (node_config const &); outbound_bandwidth_limiter::config outbound_bandwidth_limiter_config (node_config const &); @@ -69,7 +66,7 @@ outbound_bandwidth_limiter::config outbound_bandwidth_limiter_config (node_confi class node final : public std::enable_shared_from_this { public: - node (boost::asio::io_context &, uint16_t, std::filesystem::path const &, nano::logging const &, nano::work_pool &, nano::node_flags = nano::node_flags (), unsigned seq = 0); + node (boost::asio::io_context &, uint16_t, std::filesystem::path const &, nano::work_pool &, nano::node_flags = nano::node_flags (), unsigned seq = 0); node (boost::asio::io_context &, std::filesystem::path const &, nano::node_config const &, nano::work_pool &, nano::node_flags = nano::node_flags (), unsigned seq = 0); ~node (); @@ -89,24 +86,20 @@ class node final : public std::enable_shared_from_this void process_confirmed_data (store::transaction const &, std::shared_ptr const &, nano::block_hash const &, nano::account &, nano::uint128_t &, bool &, bool &, nano::account &); void process_confirmed (nano::election_status const &, uint64_t = 0); void process_active (std::shared_ptr const &); - std::optional process_local (std::shared_ptr const &); + std::optional process_local (std::shared_ptr const &); void process_local_async (std::shared_ptr const &); - void keepalive_preconfigured (std::vector const &); + void keepalive_preconfigured (); std::shared_ptr block (nano::block_hash const &); std::pair balance_pending (nano::account const &, bool only_confirmed); nano::uint128_t weight (nano::account const &); - nano::block_hash rep_block (nano::account const &); nano::uint128_t minimum_principal_weight (); - void ongoing_rep_calculation (); void ongoing_bootstrap (); void ongoing_peer_store (); - void ongoing_unchecked_cleanup (); void backup_wallet (); void search_receivable_all (); void bootstrap_wallet (); - void unchecked_cleanup (); bool collect_ledger_pruning_targets (std::deque &, nano::account &, uint64_t const, uint64_t const, uint64_t const); - void ledger_pruning (uint64_t const, bool, bool); + void ledger_pruning (uint64_t const, bool); void ongoing_ledger_pruning (); int price (nano::uint128_t const &, int); // The default difficulty updates to base only when the first epoch_2 block is processed @@ -116,9 +109,9 @@ class node final : public std::enable_shared_from_this bool local_work_generation_enabled () const; bool work_generation_enabled () const; bool work_generation_enabled (std::vector> const &) const; - boost::optional work_generate_blocking (nano::block &, uint64_t); - boost::optional work_generate_blocking (nano::work_version const, nano::root const &, uint64_t, boost::optional const & = boost::none); - void work_generate (nano::work_version const, nano::root const &, uint64_t, std::function)>, boost::optional const & = boost::none, bool const = false); + std::optional work_generate_blocking (nano::block &, uint64_t); + std::optional work_generate_blocking (nano::work_version const, nano::root const &, uint64_t, std::optional const & = std::nullopt); + void work_generate (nano::work_version const, nano::root const &, uint64_t, std::function)>, std::optional const & = std::nullopt, bool const = false); void add_initial_peers (); void start_election (std::shared_ptr const & block); bool block_confirmed (nano::block_hash const &); @@ -129,7 +122,7 @@ class node final : public std::enable_shared_from_this void ongoing_online_weight_calculation_queue (); bool online () const; bool init_error () const; - std::pair get_bootstrap_weights () const; + std::pair> get_bootstrap_weights () const; uint64_t get_confirmation_height (store::transaction const &, nano::account &); /* * Attempts to bootstrap block. This is the best effort, there is no guarantee that the block will be bootstrapped. @@ -139,25 +132,26 @@ class node final : public std::enable_shared_from_this nano::telemetry_data local_telemetry () const; public: + const nano::keypair node_id; nano::write_database_queue write_database_queue; boost::asio::io_context & io_ctx; boost::latch node_initialized_latch; nano::node_config config; nano::network_params & network_params; + nano::logger logger; nano::stats stats; nano::thread_pool workers; nano::thread_pool bootstrap_workers; nano::node_flags flags; nano::work_pool & work; nano::distributed_work_factory distributed_work; - nano::logger_mt logger; std::unique_ptr store_impl; nano::store::component & store; nano::unchecked_map unchecked; std::unique_ptr wallets_store_impl; nano::wallets_store & wallets_store; - nano::gap_cache gap_cache; - nano::ledger ledger; + std::unique_ptr ledger_impl; + nano::ledger & ledger; nano::outbound_bandwidth_limiter outbound_limiter; nano::network network; nano::telemetry telemetry; @@ -169,12 +163,11 @@ class node final : public std::enable_shared_from_this nano::port_mapping port_mapping; nano::online_reps online_reps; nano::rep_crawler rep_crawler; + nano::rep_tiers rep_tiers; nano::vote_processor vote_processor; unsigned warmed_up; nano::block_processor block_processor; - nano::block_arrival block_arrival; nano::local_vote_history history; - nano::keypair node_id; nano::block_uniquer block_uniquer; nano::vote_uniquer vote_uniquer; nano::confirmation_height_processor confirmation_height_processor; @@ -194,9 +187,7 @@ class node final : public std::enable_shared_from_this nano::bootstrap_ascending::service ascendboot; nano::websocket_server websocket; nano::epoch_upgrader epoch_upgrader; - nano::block_broadcast block_broadcast; - nano::block_publisher block_publisher; - nano::gap_tracker gap_tracker; + nano::local_block_broadcaster local_block_broadcaster; nano::process_live_dispatcher process_live_dispatcher; std::chrono::steady_clock::time_point const startup_time; @@ -208,27 +199,30 @@ class node final : public std::enable_shared_from_this // For tests only unsigned node_seq; // For tests only - boost::optional work_generate_blocking (nano::block &); + std::optional work_generate_blocking (nano::block &); // For tests only - boost::optional work_generate_blocking (nano::root const &, uint64_t); + std::optional work_generate_blocking (nano::root const &, uint64_t); // For tests only - boost::optional work_generate_blocking (nano::root const &); + std::optional work_generate_blocking (nano::root const &); public: // Testing convenience functions /** Creates a new write transaction and inserts `block' and returns result Transaction is comitted before function return */ - [[nodiscard]] nano::process_return process (nano::block & block); - [[nodiscard]] nano::process_return process (store::write_transaction const &, nano::block & block); + [[nodiscard]] nano::block_status process (std::shared_ptr block); + [[nodiscard]] nano::block_status process (store::write_transaction const &, std::shared_ptr block); nano::block_hash latest (nano::account const &); nano::uint128_t balance (nano::account const &); private: void long_inactivity_cleanup (); + + static std::string make_logger_identifier (nano::keypair const & node_id); }; -nano::keypair load_or_create_node_id (std::filesystem::path const & application_path, nano::logger_mt & logger); +nano::keypair load_or_create_node_id (std::filesystem::path const & application_path); + std::unique_ptr collect_container_info (node & node, std::string const & name); nano::node_flags const & inactive_node_flag_defaults (); diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 2453c2c24d..16f3c897b8 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -21,18 +22,18 @@ std::string const default_test_peer_network = nano::get_env_or_default ("NANO_DE } nano::node_config::node_config (nano::network_params & network_params) : - node_config (std::nullopt, nano::logging (), network_params) + node_config (std::nullopt, network_params) { } -nano::node_config::node_config (const std::optional & peering_port_a, nano::logging const & logging_a, nano::network_params & network_params) : +nano::node_config::node_config (const std::optional & peering_port_a, nano::network_params & network_params) : network_params{ network_params }, peering_port{ peering_port_a }, hinted_scheduler{ network_params.network }, - logging{ logging_a }, websocket_config{ network_params.network }, ipc_config{ network_params.network }, - external_address{ boost::asio::ip::address_v6{}.to_string () } + external_address{ boost::asio::ip::address_v6{}.to_string () }, + rep_crawler{ network_params.network } { if (peering_port == 0) { @@ -129,6 +130,8 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const toml.put ("max_work_generate_multiplier", max_work_generate_multiplier, "Maximum allowed difficulty multiplier for work generation.\ntype:double,[1..]"); toml.put ("frontiers_confirmation", serialize_frontiers_confirmation (frontiers_confirmation), "Mode controlling frontier confirmation rate.\ntype:string,{auto,always,disabled}"); toml.put ("max_queued_requests", max_queued_requests, "Limit for number of queued confirmation requests for one channel, after which new requests are dropped until the queue drops below this value.\ntype:uint32"); + toml.put ("request_aggregator_threads", request_aggregator_threads, "Number of threads to dedicate to request aggregator. Defaults to using all cpu threads, up to a maximum of 4"); + toml.put ("max_unchecked_blocks", max_unchecked_blocks, "Maximum number of unchecked blocks to store in memory. Defaults to 65536. \ntype:uint64,[0..]"); toml.put ("rep_crawler_weight_minimum", rep_crawler_weight_minimum.to_string_dec (), "Rep crawler minimum weight, if this is less than minimum principal weight then this is taken as the minimum weight a rep must have to be tracked. If you want to track all reps set this to 0. If you do not want this to influence anything then set it to max value. This is only useful for debugging or for people who really know what they are doing.\ntype:string,amount,raw"); toml.put ("backlog_scan_batch_size", backlog_scan_batch_size, "Number of accounts per second to process when doing backlog population scan. Increasing this value will help unconfirmed frontiers get into election prioritization queue faster, however it will also increase resource usage. \ntype:uint"); toml.put ("backlog_scan_frequency", backlog_scan_frequency, "Backlog scan divides the scan into smaller batches, number of which is controlled by this value. Higher frequency helps to utilize resources more uniformly, however it also introduces more overhead. The resulting number of accounts per single batch is `backlog_scan_batch_size / backlog_scan_frequency` \ntype:uint"); @@ -168,10 +171,6 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const callback_l.put ("target", callback_target, "Callback target path.\ntype:string,uri"); toml.put_child ("httpcallback", callback_l); - nano::tomlconfig logging_l; - logging.serialize_toml (logging_l); - toml.put_child ("logging", logging_l); - nano::tomlconfig websocket_l; websocket_config.serialize_toml (websocket_l); toml.put_child ("websocket", websocket_l); @@ -208,6 +207,10 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const vote_cache.serialize (vote_cache_l); toml.put_child ("vote_cache", vote_cache_l); + nano::tomlconfig rep_crawler_l; + rep_crawler.serialize (rep_crawler_l); + toml.put_child ("rep_crawler", rep_crawler_l); + return toml.get_error (); } @@ -223,12 +226,6 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) callback_l.get ("target", callback_target); } - if (toml.has_key ("logging")) - { - auto logging_l (toml.get_required_child ("logging")); - logging.deserialize_toml (logging_l); - } - if (toml.has_key ("websocket")) { auto websocket_config_l (toml.get_required_child ("websocket")); @@ -283,6 +280,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) vote_cache.deserialize (config_l); } + if (toml.has_key ("rep_crawler")) + { + auto config_l = toml.get_required_child ("rep_crawler"); + rep_crawler.deserialize (config_l); + } + if (toml.has_key ("work_peers")) { work_peers.clear (); @@ -425,6 +428,9 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) toml.get ("max_work_generate_multiplier", max_work_generate_multiplier); toml.get ("max_queued_requests", max_queued_requests); + toml.get ("request_aggregator_threads", request_aggregator_threads); + + toml.get ("max_unchecked_blocks", max_unchecked_blocks); auto rep_crawler_weight_minimum_l (rep_crawler_weight_minimum.to_string_dec ()); if (toml.has_key ("rep_crawler_weight_minimum")) @@ -568,4 +574,4 @@ nano::account nano::node_config::random_representative () const std::size_t index (nano::random_pool::generate_word32 (0, static_cast (preconfigured_representatives.size () - 1))); auto result (preconfigured_representatives[index]); return result; -} \ No newline at end of file +} diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 0cc4116270..cf778df4ee 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -4,17 +4,19 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include #include #include #include +#include #include #include @@ -39,18 +41,18 @@ class node_config { public: node_config (nano::network_params & network_params = nano::dev::network_params); - node_config (const std::optional &, nano::logging const &, nano::network_params & network_params = nano::dev::network_params); + node_config (const std::optional &, nano::network_params & network_params = nano::dev::network_params); nano::error serialize_toml (nano::tomlconfig &) const; nano::error deserialize_toml (nano::tomlconfig &); bool upgrade_json (unsigned, nano::jsonconfig &); nano::account random_representative () const; + nano::network_params network_params; std::optional peering_port{}; nano::scheduler::optimistic_config optimistic_scheduler; nano::scheduler::hinted_config hinted_scheduler; - nano::logging logging; std::vector> work_peers; std::vector> secondary_work_peers{ { "127.0.0.1", 8076 } }; /* Default of nano-pow-server */ std::vector preconfigured_peers; @@ -88,7 +90,7 @@ class node_config uint16_t external_port{ 0 }; std::chrono::milliseconds block_processor_batch_max_time{ std::chrono::milliseconds (500) }; /** Time to wait for block processing result */ - std::chrono::seconds block_process_timeout{ 15 }; + std::chrono::seconds block_process_timeout{ 300 }; std::chrono::seconds unchecked_cutoff_time{ std::chrono::seconds (4 * 60 * 60) }; // 4 hours /** Timeout for initiated async operations */ std::chrono::seconds tcp_io_timeout{ (network_params.network.is_dev_network () && !is_sanitizer_build ()) ? std::chrono::seconds (5) : std::chrono::seconds (15) }; @@ -116,6 +118,8 @@ class node_config bool backup_before_upgrade{ false }; double max_work_generate_multiplier{ 64. }; uint32_t max_queued_requests{ 512 }; + unsigned request_aggregator_threads{ std::min (nano::hardware_concurrency (), 4u) }; // Max 4 threads if available + unsigned max_unchecked_blocks{ 65536 }; std::chrono::seconds max_pruning_age{ !network_params.network.is_beta_network () ? std::chrono::seconds (24 * 60 * 60) : std::chrono::seconds (5 * 60) }; // 1 day; 5 minutes for beta network uint64_t max_pruning_depth{ 0 }; nano::rocksdb_config rocksdb_config; @@ -126,6 +130,7 @@ class node_config /** Number of times per second to run backlog population batches. Number of accounts per single batch is `backlog_scan_batch_size / backlog_scan_frequency` */ unsigned backlog_scan_frequency{ 10 }; nano::vote_cache_config vote_cache; + nano::rep_crawler_config rep_crawler; public: std::string serialize_frontiers_confirmation (nano::frontiers_confirmation_mode) const; @@ -152,8 +157,6 @@ class node_flags final bool disable_rep_crawler{ false }; bool disable_request_loop{ false }; // For testing only bool disable_tcp_realtime{ false }; - bool disable_unchecked_cleanup{ false }; - bool disable_unchecked_drop{ true }; bool disable_providing_telemetry_metrics{ false }; bool disable_ongoing_telemetry_requests{ false }; bool disable_block_processor_unchecked_deletion{ false }; @@ -168,7 +171,7 @@ class node_flags final bool read_only{ false }; bool disable_connection_cleanup{ false }; nano::confirmation_height_mode confirmation_height_processor_mode{ nano::confirmation_height_mode::automatic }; - nano::generate_cache generate_cache; + nano::generate_cache_flags generate_cache; bool inactive_node{ false }; std::size_t block_processor_batch_size{ 0 }; std::size_t block_processor_full_size{ 65536 }; diff --git a/nano/node/online_reps.hpp b/nano/node/online_reps.hpp index 8b07e9a5d2..f01fec91e0 100644 --- a/nano/node/online_reps.hpp +++ b/nano/node/online_reps.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -15,6 +16,10 @@ namespace nano { class ledger; class node_config; +namespace store +{ + class transaction; +} /** Track online representatives and trend online weight */ class online_reps final diff --git a/nano/node/openclwork.cpp b/nano/node/openclwork.cpp index 8389a19fb3..1e8907797d 100644 --- a/nano/node/openclwork.cpp +++ b/nano/node/openclwork.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -249,7 +250,7 @@ void nano::opencl_environment::dump (std::ostream & stream) } } -nano::opencl_work::opencl_work (bool & error_a, nano::opencl_config const & config_a, nano::opencl_environment & environment_a, nano::logger_mt & logger_a, nano::work_thresholds & work) : +nano::opencl_work::opencl_work (bool & error_a, nano::opencl_config const & config_a, nano::opencl_environment & environment_a, nano::logger & logger_a, nano::work_thresholds & work) : config (config_a), context (0), attempt_buffer (0), @@ -343,85 +344,85 @@ nano::opencl_work::opencl_work (bool & error_a, nano::opencl_config const & conf } else { - logger.always_log (boost::str (boost::format ("Bind argument 3 error %1%") % arg3_error)); + logger.error (nano::log::type::opencl_work, "Bind argument 3 error: {}", arg3_error); } } else { - logger.always_log (boost::str (boost::format ("Bind argument 2 error %1%") % arg2_error)); + logger.error (nano::log::type::opencl_work, "Bind argument 2 error: {}", arg2_error); } } else { - logger.always_log (boost::str (boost::format ("Bind argument 1 error %1%") % arg1_error)); + logger.error (nano::log::type::opencl_work, "Bind argument 1 error: {}", arg1_error); } } else { - logger.always_log (boost::str (boost::format ("Bind argument 0 error %1%") % arg0_error)); + logger.error (nano::log::type::opencl_work, "Bind argument 0 error: {}", arg0_error); } } else { - logger.always_log (boost::str (boost::format ("Create kernel error %1%") % kernel_error)); + logger.error (nano::log::type::opencl_work, "Create kernel error: {}", kernel_error); } } else { - logger.always_log (boost::str (boost::format ("Build program error %1%") % clBuildProgramError)); + logger.error (nano::log::type::opencl_work, "Build program error: {}", clBuildProgramError); for (auto i (selected_devices.begin ()), n (selected_devices.end ()); i != n; ++i) { std::size_t log_size (0); clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size); std::vector log (log_size); clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, log.size (), log.data (), nullptr); - logger.always_log (log.data ()); + logger.info (nano::log::type::opencl_work, "Device log: {}", log.data ()); } } } else { - logger.always_log (boost::str (boost::format ("Create program error %1%") % program_error)); + logger.error (nano::log::type::opencl_work, "Create program error: {}", program_error); } } else { - logger.always_log (boost::str (boost::format ("Difficulty buffer error %1%") % difficulty_error)); + logger.error (nano::log::type::opencl_work, "Difficulty buffer error: {}", difficulty_error); } } else { - logger.always_log (boost::str (boost::format ("Item buffer error %1%") % item_error)); + logger.error (nano::log::type::opencl_work, "Item buffer error: {}", item_error); } } else { - logger.always_log (boost::str (boost::format ("Result buffer error %1%") % result_error)); + logger.error (nano::log::type::opencl_work, "Result buffer error: {}", result_error); } } else { - logger.always_log (boost::str (boost::format ("Attempt buffer error %1%") % attempt_error)); + logger.error (nano::log::type::opencl_work, "Attempt buffer error: {}", attempt_error); } } else { - logger.always_log (boost::str (boost::format ("Unable to create command queue %1%") % queue_error)); + logger.error (nano::log::type::opencl_work, "Unable to create command queue: {}", queue_error); } } else { - logger.always_log (boost::str (boost::format ("Unable to create context %1%") % createContextError)); + logger.error (nano::log::type::opencl_work, "Unable to create context: {}", createContextError); } } else { - logger.always_log (boost::str (boost::format ("Requested device %1%, and only have %2%") % config.device % platform.devices.size ())); + logger.error (nano::log::type::opencl_work, "Requested device {} and only have {}", config.device, platform.devices.size ()); } } else { - logger.always_log (boost::str (boost::format ("Requested platform %1% and only have %2%") % config.platform % environment_a.platforms.size ())); + logger.error (nano::log::type::opencl_work, "Requested platform {} and only have {}", config.platform, environment_a.platforms.size ()); } } @@ -480,37 +481,37 @@ boost::optional nano::opencl_work::generate_work (nano::work_version c else { error = true; - logger.always_log (boost::str (boost::format ("Error finishing queue %1%") % finishError)); + logger.error (nano::log::type::opencl_work, "Error finishing queue: {}", finishError); } } else { error = true; - logger.always_log (boost::str (boost::format ("Error reading result %1%") % read_error1)); + logger.error (nano::log::type::opencl_work, "Error reading result: {}", read_error1); } } else { error = true; - logger.always_log (boost::str (boost::format ("Error enqueueing kernel %1%") % enqueue_error)); + logger.error (nano::log::type::opencl_work, "Error enqueueing kernel: {}", enqueue_error); } } else { error = true; - logger.always_log (boost::str (boost::format ("Error writing item %1%") % write_error3)); + logger.error (nano::log::type::opencl_work, "Error writing difficulty: {}", write_error3); } } else { error = true; - logger.always_log (boost::str (boost::format ("Error writing item %1%") % write_error2)); + logger.error (nano::log::type::opencl_work, "Error writing item: {}", write_error2); } } else { error = true; - logger.always_log (boost::str (boost::format ("Error writing attempt %1%") % write_error1)); + logger.error (nano::log::type::opencl_work, "Error writing attempt: {}", write_error1); } } boost::optional value; @@ -521,16 +522,18 @@ boost::optional nano::opencl_work::generate_work (nano::work_version c return value; } -std::unique_ptr nano::opencl_work::create (bool create_a, nano::opencl_config const & config_a, nano::logger_mt & logger_a, nano::work_thresholds & work) +std::unique_ptr nano::opencl_work::create (bool create_a, nano::opencl_config const & config_a, nano::logger & logger_a, nano::work_thresholds & work) { std::unique_ptr result; if (create_a) { auto error (false); + nano::opencl_environment environment (error); std::stringstream stream; environment.dump (stream); - logger_a.always_log (stream.str ()); + logger_a.info (nano::log::type::opencl_work, "OpenCL environment: {}", stream.str ()); + if (!error) { result.reset (new nano::opencl_work (error, config_a, environment, logger_a, work)); diff --git a/nano/node/openclwork.hpp b/nano/node/openclwork.hpp index 2f452e092e..c73b988440 100644 --- a/nano/node/openclwork.hpp +++ b/nano/node/openclwork.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -21,13 +21,15 @@ namespace nano { extern bool opencl_loaded; -class logger_mt; +class logger; + class opencl_platform { public: cl_platform_id platform; std::vector devices; }; + class opencl_environment { public: @@ -35,16 +37,18 @@ class opencl_environment void dump (std::ostream & stream); std::vector platforms; }; + class root; class work_pool; + class opencl_work { public: - opencl_work (bool &, nano::opencl_config const &, nano::opencl_environment &, nano::logger_mt &, nano::work_thresholds & work); + opencl_work (bool &, nano::opencl_config const &, nano::opencl_environment &, nano::logger &, nano::work_thresholds & work); ~opencl_work (); boost::optional generate_work (nano::work_version const, nano::root const &, uint64_t const); boost::optional generate_work (nano::work_version const, nano::root const &, uint64_t const, std::atomic &); - static std::unique_ptr create (bool, nano::opencl_config const &, nano::logger_mt &, nano::work_thresholds & work); + static std::unique_ptr create (bool, nano::opencl_config const &, nano::logger &, nano::work_thresholds & work); nano::opencl_config const & config; nano::mutex mutex; cl_context context; @@ -56,7 +60,7 @@ class opencl_work cl_kernel kernel; cl_command_queue queue; nano::xorshift1024star rand; - nano::logger_mt & logger; + nano::logger & logger; nano::work_thresholds & work; }; } diff --git a/nano/node/portmapping.cpp b/nano/node/portmapping.cpp index 690b7ce907..e8d01e847f 100644 --- a/nano/node/portmapping.cpp +++ b/nano/node/portmapping.cpp @@ -60,17 +60,19 @@ void nano::port_mapping::refresh_devices () std::array local_address_l; local_address_l.fill (0); auto igd_error_l (UPNP_GetValidIGD (upnp_l.devices, &upnp_l.urls, &upnp_l.data, local_address_l.data (), sizeof (local_address_l))); - if (check_count % 15 == 0 || node.config.logging.upnp_details_logging ()) + + // Bump logging level periodically + node.logger.log ((check_count % 15 == 0) ? nano::log::level::info : nano::log::level::debug, + nano::log::type::upnp, "UPnP local address {}, discovery: {}, IGD search: {}", + local_address_l.data (), + discover_error_l, + igd_error_l); + + for (auto i (upnp_l.devices); i != nullptr; i = i->pNext) { - node.logger.always_log (boost::str (boost::format ("UPnP local address: %1%, discovery: %2%, IGD search: %3%") % local_address_l.data () % discover_error_l % igd_error_l)); - if (node.config.logging.upnp_details_logging ()) - { - for (auto i (upnp_l.devices); i != nullptr; i = i->pNext) - { - node.logger.always_log (boost::str (boost::format ("UPnP device url: %1% st: %2% usn: %3%") % i->descURL % i->st % i->usn)); - } - } + node.logger.debug (nano::log::type::upnp, "UPnP device url: {}, st: {}, usn: {}", i->descURL, i->st, i->usn); } + // Update port mapping nano::lock_guard guard_l (mutex); upnp = std::move (upnp_l); @@ -114,14 +116,23 @@ void nano::port_mapping::refresh_mapping () if (add_port_mapping_error_l == UPNPCOMMAND_SUCCESS) { protocol.external_port = static_cast (std::atoi (config_port_l.data ())); - auto fmt = boost::format ("UPnP %1% %2%:%3% mapped to %4%") % protocol.name % protocol.external_address % config_port_l % node_port_l; - node.logger.always_log (boost::str (fmt)); + + node.logger.info (nano::log::type::upnp, "UPnP {} {}:{} mapped to: {}", + protocol.name, + protocol.external_address.to_string (), + config_port_l, + node_port_l); } else { protocol.external_port = 0; - auto fmt = boost::format ("UPnP %1% %2%:%3% FAILED") % protocol.name % add_port_mapping_error_l % strupnperror (add_port_mapping_error_l); - node.logger.always_log (boost::str (fmt)); + + node.logger.warn (nano::log::type::upnp, "UPnP {} {}:{} failed: {} ({})", + protocol.name, + protocol.external_address.to_string (), + config_port_l, + add_port_mapping_error_l, + strupnperror (add_port_mapping_error_l)); } } } @@ -149,12 +160,19 @@ bool nano::port_mapping::check_lost_or_old_mapping () if (verify_port_mapping_error_l != UPNPCOMMAND_SUCCESS) { result_l = true; - node.logger.always_log (boost::str (boost::format ("UPNP_GetSpecificPortMappingEntry failed %1%: %2%") % verify_port_mapping_error_l % strupnperror (verify_port_mapping_error_l))); + + node.logger.warn (nano::log::type::upnp, "UPnP get specific port mapping failed: {} ({})", + verify_port_mapping_error_l, + strupnperror (verify_port_mapping_error_l)); } if (!recent_lease) { result_l = true; - node.logger.always_log (boost::str (boost::format ("UPnP leasing time getting old, remaining time: %1%, lease time: %2%, below the threshold: %3%") % remaining_from_port_mapping % lease_duration % lease_duration_divided_by_two)); + + node.logger.info (nano::log::type::upnp, "UPnP lease time getting old, remaining time: {}, lease time: {}, below the threshold: {}", + remaining_from_port_mapping, + lease_duration, + lease_duration_divided_by_two); } std::array external_address_l; external_address_l.fill (0); @@ -168,12 +186,19 @@ bool nano::port_mapping::check_lost_or_old_mapping () else { protocol.external_address = boost::asio::ip::address_v4::any (); - node.logger.always_log (boost::str (boost::format ("UPNP_GetExternalIPAddress failed %1%: %2%") % verify_port_mapping_error_l % strupnperror (verify_port_mapping_error_l))); - } - if (node.config.logging.upnp_details_logging ()) - { - node.logger.always_log (boost::str (boost::format ("UPnP %1% mapping verification response: %2%, external ip response: %3%, external ip: %4%, internal ip: %5%, remaining lease: %6%") % protocol.name % verify_port_mapping_error_l % external_ip_error_l % external_address_l.data () % address.to_string () % remaining_mapping_duration_l.data ())); + + node.logger.warn (nano::log::type::upnp, "UPnP get external ip address failed: {} ({})", + external_ip_error_l, + strupnperror (external_ip_error_l)); } + + node.logger.debug (nano::log::type::upnp, "UPnP {} mapping verification response: {}, external ip response: {}, external ip: {}, internal ip: {}, remaining lease: {}", + protocol.name, + verify_port_mapping_error_l, + external_ip_error_l, + external_address_l.data (), + address.to_string (), + remaining_mapping_duration_l.data ()); } return result_l; } @@ -194,15 +219,14 @@ void nano::port_mapping::check_mapping_loop () } else { - node.logger.always_log (boost::str (boost::format ("UPnP No need to refresh the mapping"))); + node.logger.info (nano::log::type::upnp, "UPnP No need to refresh the mapping"); } } else { - if (check_count < 10 || node.config.logging.upnp_details_logging ()) - { - node.logger.always_log (boost::str (boost::format ("UPnP No IGD devices found"))); - } + // Bump logging level periodically + node.logger.log ((check_count % 15 == 0) ? nano::log::level::info : nano::log::level::debug, + nano::log::type::upnp, "UPnP No IGD devices found"); } // Check for new devices or after health_check_period @@ -225,11 +249,17 @@ void nano::port_mapping::stop () auto delete_error_l (UPNP_DeletePortMapping (upnp.urls.controlURL, upnp.data.first.servicetype, std::to_string (protocol.external_port).c_str (), protocol.name, address.to_string ().c_str ())); if (delete_error_l) { - node.logger.always_log (boost::str (boost::format ("UPnP shutdown %1% port mapping response: %2%") % protocol.name % delete_error_l)); + node.logger.warn (nano::log::type::upnp, "UPnP shutdown {} port mapping failed: {} ({})", + protocol.name, + delete_error_l, + strupnperror (delete_error_l)); } else { - node.logger.always_log (boost::str (boost::format ("UPnP shutdown %1% port mapping successful: %2%:%3%") % protocol.name % protocol.external_address % protocol.external_port)); + node.logger.info (nano::log::type::upnp, "UPnP shutdown {} port mapping successful: {}:{}", + protocol.name, + protocol.external_address.to_string (), + protocol.external_port); } } } diff --git a/nano/node/process_live_dispatcher.cpp b/nano/node/process_live_dispatcher.cpp index c7a6d16dbf..f0d457dbef 100644 --- a/nano/node/process_live_dispatcher.cpp +++ b/nano/node/process_live_dispatcher.cpp @@ -20,19 +20,19 @@ void nano::process_live_dispatcher::connect (nano::block_processor & block_proce { block_processor.batch_processed.add ([this] (auto const & batch) { auto const transaction = ledger.store.tx_begin_read (); - for (auto const & [result, block] : batch) + for (auto const & [result, context] : batch) { - debug_assert (block != nullptr); - inspect (result, *block, transaction); + debug_assert (context.block != nullptr); + inspect (result, *context.block, transaction); } }); } -void nano::process_live_dispatcher::inspect (nano::process_return const & result, nano::block const & block, store::transaction const & transaction) +void nano::process_live_dispatcher::inspect (nano::block_status const & result, nano::block const & block, store::transaction const & transaction) { - switch (result.code) + switch (result) { - case nano::process_result::progress: + case nano::block_status::progress: process_live (block, transaction); break; default: @@ -45,8 +45,7 @@ void nano::process_live_dispatcher::process_live (nano::block const & block, sto // Start collecting quorum on block if (ledger.dependents_confirmed (transaction, block)) { - auto account = block.account ().is_zero () ? block.sideband ().account : block.account (); - scheduler.activate (account, transaction); + scheduler.activate (block.account (), transaction); } if (websocket.server && websocket.server->any_subscriber (nano::websocket::topic::new_unconfirmed_block)) diff --git a/nano/node/process_live_dispatcher.hpp b/nano/node/process_live_dispatcher.hpp index ec30d94913..210656eb7c 100644 --- a/nano/node/process_live_dispatcher.hpp +++ b/nano/node/process_live_dispatcher.hpp @@ -28,7 +28,7 @@ class process_live_dispatcher private: // Block_processor observer - void inspect (nano::process_return const & result, nano::block const & block, store::transaction const & transaction); + void inspect (nano::block_status const & result, nano::block const & block, store::transaction const & transaction); void process_live (nano::block const & block, store::transaction const & transaction); nano::ledger & ledger; diff --git a/nano/node/rep_tiers.cpp b/nano/node/rep_tiers.cpp new file mode 100644 index 0000000000..7b0cffb47d --- /dev/null +++ b/nano/node/rep_tiers.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; + +nano::rep_tiers::rep_tiers (nano::ledger & ledger_a, nano::network_params & network_params_a, nano::online_reps & online_reps_a, nano::stats & stats_a, nano::logger & logger_a) : + ledger{ ledger_a }, + network_params{ network_params_a }, + online_reps{ online_reps_a }, + stats{ stats_a }, + logger{ logger_a } +{ +} + +nano::rep_tiers::~rep_tiers () +{ + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); +} + +void nano::rep_tiers::start () +{ + debug_assert (!thread.joinable ()); + + thread = std::thread{ [this] () { + nano::thread_role::set (nano::thread_role::name::rep_tiers); + run (); + } }; +} + +void nano::rep_tiers::stop () +{ + { + nano::lock_guard lock{ mutex }; + stopped = true; + } + condition.notify_all (); + if (thread.joinable ()) + { + thread.join (); + } +} + +nano::rep_tier nano::rep_tiers::tier (const nano::account & representative) const +{ + nano::lock_guard lock{ mutex }; + if (representatives_3.find (representative) != representatives_3.end ()) + { + return nano::rep_tier::tier_3; + } + if (representatives_2.find (representative) != representatives_2.end ()) + { + return nano::rep_tier::tier_2; + } + if (representatives_1.find (representative) != representatives_1.end ()) + { + return nano::rep_tier::tier_1; + } + return nano::rep_tier::none; +} + +void nano::rep_tiers::run () +{ + nano::unique_lock lock{ mutex }; + while (!stopped) + { + stats.inc (nano::stat::type::rep_tiers, nano::stat::detail::loop); + + lock.unlock (); + + calculate_tiers (); + + lock.lock (); + + std::chrono::milliseconds interval = network_params.network.is_dev_network () ? 500ms : 10min; + condition.wait_for (lock, interval); + } +} + +void nano::rep_tiers::calculate_tiers () +{ + auto stake = online_reps.trended (); + auto rep_amounts = ledger.cache.rep_weights.get_rep_amounts (); + + decltype (representatives_1) representatives_1_l; + decltype (representatives_2) representatives_2_l; + decltype (representatives_3) representatives_3_l; + + int ignored = 0; + for (auto const & rep_amount : rep_amounts) + { + nano::account const & representative = rep_amount.first; + + // Using ledger weight here because it takes preconfigured bootstrap weights into account + auto weight = ledger.weight (representative); + if (weight > stake / 1000) // 0.1% or above (level 1) + { + representatives_1_l.insert (representative); + if (weight > stake / 100) // 1% or above (level 2) + { + representatives_2_l.insert (representative); + if (weight > stake / 20) // 5% or above (level 3) + { + representatives_3_l.insert (representative); + } + } + } + else + { + ++ignored; + } + } + + stats.add (nano::stat::type::rep_tiers, nano::stat::detail::processed, nano::stat::dir::in, rep_amounts.size ()); + stats.add (nano::stat::type::rep_tiers, nano::stat::detail::ignored, nano::stat::dir::in, ignored); + logger.debug (nano::log::type::rep_tiers, "Representative tiers updated, tier 1: {}, tier 2: {}, tier 3: {} ({} ignored)", + representatives_1_l.size (), + representatives_2_l.size (), + representatives_3_l.size (), + ignored); + + { + nano::lock_guard guard{ mutex }; + representatives_1 = std::move (representatives_1_l); + representatives_2 = std::move (representatives_2_l); + representatives_3 = std::move (representatives_3_l); + } + + stats.inc (nano::stat::type::rep_tiers, nano::stat::detail::updated); +} + +std::unique_ptr nano::rep_tiers::collect_container_info (const std::string & name) +{ + nano::lock_guard lock{ mutex }; + auto composite = std::make_unique (name); + composite->add_component (std::make_unique (container_info{ "representatives_1", representatives_1.size (), sizeof (decltype (representatives_1)::value_type) })); + composite->add_component (std::make_unique (container_info{ "representatives_2", representatives_2.size (), sizeof (decltype (representatives_2)::value_type) })); + composite->add_component (std::make_unique (container_info{ "representatives_3", representatives_3.size (), sizeof (decltype (representatives_3)::value_type) })); + return composite; +} \ No newline at end of file diff --git a/nano/node/rep_tiers.hpp b/nano/node/rep_tiers.hpp new file mode 100644 index 0000000000..ce989d8e0a --- /dev/null +++ b/nano/node/rep_tiers.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace nano +{ +class ledger; +class network_params; +class stats; +class logger; +class container_info_component; +class online_reps; + +// Higher number means higher priority +enum class rep_tier +{ + none, // Not a principal representatives + tier_1, // (0.1-1%) of online stake + tier_2, // (1-5%) of online stake + tier_3, // (> 5%) of online stake +}; + +class rep_tiers final +{ +public: + rep_tiers (nano::ledger &, nano::network_params &, nano::online_reps &, nano::stats &, nano::logger &); + ~rep_tiers (); + + void start (); + void stop (); + + /** Returns the representative tier for the account */ + nano::rep_tier tier (nano::account const & representative) const; + + std::unique_ptr collect_container_info (std::string const & name); + +private: // Dependencies + nano::ledger & ledger; + nano::network_params & network_params; + nano::online_reps & online_reps; + nano::stats & stats; + nano::logger & logger; + +private: + void run (); + void calculate_tiers (); + +private: + /** Representatives levels for early prioritization */ + std::unordered_set representatives_1; + std::unordered_set representatives_2; + std::unordered_set representatives_3; + + std::atomic stopped{ false }; + nano::condition_variable condition; + mutable nano::mutex mutex; + std::thread thread; +}; +} \ No newline at end of file diff --git a/nano/node/repcrawler.cpp b/nano/node/repcrawler.cpp index 0d637b1483..adf2fd2fe1 100644 --- a/nano/node/repcrawler.cpp +++ b/nano/node/repcrawler.cpp @@ -1,93 +1,118 @@ #include #include +#include -#include +#include -nano::rep_crawler::rep_crawler (nano::node & node_a) : - node (node_a) +nano::rep_crawler::rep_crawler (nano::rep_crawler_config const & config_a, nano::node & node_a) : + config{ config_a }, + node{ node_a }, + stats{ node_a.stats }, + logger{ node_a.logger }, + network_constants{ node_a.network_params.network }, + active{ node_a.active } { if (!node.flags.disable_rep_crawler) { - node.observers.endpoint.add ([this] (std::shared_ptr const & channel_a) { - this->query (channel_a); + node.observers.endpoint.add ([this] (std::shared_ptr const & channel) { + query (channel); }); } } -void nano::rep_crawler::remove (nano::block_hash const & hash_a) +nano::rep_crawler::~rep_crawler () { - nano::lock_guard lock{ active_mutex }; - active.erase (hash_a); + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); } void nano::rep_crawler::start () { - ongoing_crawl (); + debug_assert (!thread.joinable ()); + + thread = std::thread{ [this] () { + nano::thread_role::set (nano::thread_role::name::rep_crawler); + run (); + } }; } -void nano::rep_crawler::validate () +void nano::rep_crawler::stop () { - decltype (responses) responses_l; { - nano::lock_guard lock{ active_mutex }; - responses_l.swap (responses); + nano::lock_guard lock{ mutex }; + stopped = true; + } + condition.notify_all (); + if (thread.joinable ()) + { + thread.join (); } +} + +// Exits with the lock unlocked +void nano::rep_crawler::validate_and_process (nano::unique_lock & lock) +{ + debug_assert (!mutex.try_lock ()); + debug_assert (lock.owns_lock ()); + debug_assert (!responses.empty ()); // Should be checked before calling this function + + decltype (responses) responses_l{ responses.capacity () }; + responses_l.swap (responses); + + lock.unlock (); // normally the rep_crawler only tracks principal reps but it can be made to track // reps with less weight by setting rep_crawler_weight_minimum to a low value - auto minimum = std::min (node.minimum_principal_weight (), node.config.rep_crawler_weight_minimum.number ()); + auto const minimum = std::min (node.minimum_principal_weight (), node.config.rep_crawler_weight_minimum.number ()); - for (auto const & i : responses_l) + // TODO: Is it really faster to repeatedly lock/unlock the mutex for each response? + for (auto const & response : responses_l) { - auto & vote = i.second; - auto & channel = i.first; - debug_assert (channel != nullptr); + auto & vote = response.second; + auto & channel = response.first; + release_assert (vote != nullptr); + release_assert (channel != nullptr); if (channel->get_type () == nano::transport::transport_type::loopback) { - if (node.config.logging.rep_crawler_logging ()) - { - node.logger.try_log (boost::str (boost::format ("rep_crawler ignoring vote from loopback channel %1%") % channel->to_string ())); - } + logger.debug (nano::log::type::rep_crawler, "Ignoring vote from loopback channel: {}", channel->to_string ()); continue; } - nano::uint128_t rep_weight = node.ledger.weight (vote->account); + nano::uint128_t const rep_weight = node.ledger.weight (vote->account); if (rep_weight < minimum) { - if (node.config.logging.rep_crawler_logging ()) - { - node.logger.try_log (boost::str (boost::format ("rep_crawler ignoring vote from account %1% with too little voting weight %2%") % vote->account.to_account () % rep_weight)); - } + logger.debug (nano::log::type::rep_crawler, "Ignoring vote from account {} with too little voting weight: {}", + vote->account.to_account (), + nano::util::to_str (rep_weight)); continue; } // temporary data used for logging after dropping the lock - auto inserted = false; - auto updated = false; + bool inserted = false; + bool updated = false; std::shared_ptr prev_channel; - nano::unique_lock lock{ probable_reps_mutex }; + lock.lock (); - auto existing (probable_reps.find (vote->account)); - if (existing != probable_reps.end ()) + if (auto existing = reps.find (vote->account); existing != reps.end ()) { - probable_reps.modify (existing, [rep_weight, &updated, &vote, &channel, &prev_channel] (nano::representative & info) { - info.last_response = std::chrono::steady_clock::now (); + reps.modify (existing, [rep_weight, &updated, &vote, &channel, &prev_channel] (rep_entry & rep) { + rep.last_response = std::chrono::steady_clock::now (); // Update if representative channel was changed - if (info.channel->get_endpoint () != channel->get_endpoint ()) + if (rep.channel->get_endpoint () != channel->get_endpoint ()) { - debug_assert (info.account == vote->account); + debug_assert (rep.account == vote->account); updated = true; - prev_channel = info.channel; - info.channel = channel; + prev_channel = rep.channel; + rep.channel = channel; } }); } else { - probable_reps.emplace (nano::representative (vote->account, channel)); + reps.emplace (rep_entry{ vote->account, channel }); inserted = true; } @@ -95,279 +120,415 @@ void nano::rep_crawler::validate () if (inserted) { - node.logger.try_log (boost::str (boost::format ("Found representative %1% at %2%") % vote->account.to_account () % channel->to_string ())); + logger.info (nano::log::type::rep_crawler, "Found representative {} at {}", vote->account.to_account (), channel->to_string ()); } - if (updated) { - node.logger.try_log (boost::str (boost::format ("Updated representative %1% at %2% (was at: %3%)") % vote->account.to_account () % channel->to_string () % prev_channel->to_string ())); + logger.warn (nano::log::type::rep_crawler, "Updated representative {} at {} (was at: {})", vote->account.to_account (), channel->to_string (), prev_channel->to_string ()); } } } -void nano::rep_crawler::ongoing_crawl () +std::chrono::milliseconds nano::rep_crawler::query_interval (bool sufficient_weight) const +{ + return sufficient_weight ? network_constants.rep_crawler_normal_interval : network_constants.rep_crawler_warmup_interval; +} + +bool nano::rep_crawler::query_predicate (bool sufficient_weight) const +{ + return nano::elapsed (last_query, query_interval (sufficient_weight)); +} + +void nano::rep_crawler::run () { - auto now (std::chrono::steady_clock::now ()); - auto total_weight_l (total_weight ()); - cleanup_reps (); - validate (); - query (get_crawl_targets (total_weight_l)); - auto sufficient_weight (total_weight_l > node.online_reps.delta ()); - // If online weight drops below minimum, reach out to preconfigured peers - if (!sufficient_weight) + nano::unique_lock lock{ mutex }; + while (!stopped) { - node.keepalive_preconfigured (node.config.preconfigured_peers); + lock.unlock (); + + auto const current_total_weight = total_weight (); + bool const sufficient_weight = current_total_weight > node.online_reps.delta (); + + // If online weight drops below minimum, reach out to preconfigured peers + if (!sufficient_weight) + { + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::keepalive); + node.keepalive_preconfigured (); + } + + lock.lock (); + + condition.wait_for (lock, query_interval (sufficient_weight), [this, sufficient_weight] { + return stopped || query_predicate (sufficient_weight) || !responses.empty (); + }); + + if (stopped) + { + return; + } + + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::loop); + + if (!responses.empty ()) + { + validate_and_process (lock); + debug_assert (!lock.owns_lock ()); + lock.lock (); + } + + cleanup (); + + if (query_predicate (sufficient_weight)) + { + last_query = std::chrono::steady_clock::now (); + + auto targets = prepare_crawl_targets (sufficient_weight); + + lock.unlock (); + query (targets); + lock.lock (); + } + + debug_assert (lock.owns_lock ()); } - // Reduce crawl frequency when there's enough total peer weight - unsigned next_run_ms = node.network_params.network.is_dev_network () ? 100 : sufficient_weight ? 7000 - : 3000; - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (now + std::chrono::milliseconds (next_run_ms), [node_w, this] () { - if (auto node_l = node_w.lock ()) +} + +void nano::rep_crawler::cleanup () +{ + debug_assert (!mutex.try_lock ()); + + // Evict reps with dead channels + erase_if (reps, [this] (rep_entry const & rep) { + if (!rep.channel->alive ()) + { + logger.info (nano::log::type::rep_crawler, "Evicting representative {} with dead channel at {}", rep.account.to_account (), rep.channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::channel_dead); + return true; // Erase + } + return false; + }); + + // Evict queries that haven't been responded to in a while + erase_if (queries, [this] (query_entry const & query) { + if (nano::elapsed (query.time, config.query_timeout)) { - this->ongoing_crawl (); + if (query.replies == 0) + { + logger.debug (nano::log::type::rep_crawler, "Aborting unresponsive query for block {} from {}", query.hash.to_string (), query.channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_timeout); + } + else + { + logger.debug (nano::log::type::rep_crawler, "Completion of query with {} replies for block {} from {}", query.replies, query.hash.to_string (), query.channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_completion); + } + return true; // Erase } + return false; }); } -std::vector> nano::rep_crawler::get_crawl_targets (nano::uint128_t total_weight_a) +std::vector> nano::rep_crawler::prepare_crawl_targets (bool sufficient_weight) const { - constexpr std::size_t conservative_count = 10; - constexpr std::size_t aggressive_count = 40; + debug_assert (!mutex.try_lock ()); + + // TODO: Make these values configurable + constexpr std::size_t conservative_count = 160; + constexpr std::size_t aggressive_count = 160; + constexpr std::size_t conservative_max_attempts = 4; + constexpr std::size_t aggressive_max_attempts = 8; + std::chrono::milliseconds rep_query_interval = node.network_params.network.is_dev_network () ? std::chrono::milliseconds{ 500 } : std::chrono::milliseconds{ 60 * 1000 }; + + stats.inc (nano::stat::type::rep_crawler, sufficient_weight ? nano::stat::detail::crawl_normal : nano::stat::detail::crawl_aggressive); // Crawl more aggressively if we lack sufficient total peer weight. - bool sufficient_weight (total_weight_a > node.online_reps.delta ()); - uint16_t required_peer_count = sufficient_weight ? conservative_count : aggressive_count; - - // Add random peers. We do this even if we have enough weight, in order to pick up reps - // that didn't respond when first observed. If the current total weight isn't sufficient, this - // will be more aggressive. When the node first starts, the rep container is empty and all - // endpoints will originate from random peers. - required_peer_count += required_peer_count / 2; - - // The rest of the endpoints are picked randomly - auto random_peers (node.network.random_set (required_peer_count, 0, true)); // Include channels with ephemeral remote ports - std::vector> result; - result.insert (result.end (), random_peers.begin (), random_peers.end ()); - return result; + auto const required_peer_count = sufficient_weight ? conservative_count : aggressive_count; + + auto random_peers = node.network.random_set (required_peer_count, 0, /* include channels with ephemeral remote ports */ true); + + auto should_query = [&, this] (std::shared_ptr const & channel) { + if (auto rep = reps.get ().find (channel); rep != reps.get ().end ()) + { + // Throttle queries to active reps + return elapsed (rep->last_request, rep_query_interval); + } + else + { + // Avoid querying the same peer multiple times when rep crawler is warmed up + auto const max_attempts = sufficient_weight ? conservative_max_attempts : aggressive_max_attempts; + return queries.get ().count (channel) < max_attempts; + } + }; + + erase_if (random_peers, [&, this] (std::shared_ptr const & channel) { + return !should_query (channel); + }); + + return { random_peers.begin (), random_peers.end () }; } -void nano::rep_crawler::query (std::vector> const & channels_a) +auto nano::rep_crawler::prepare_query_target () -> std::optional { - auto transaction (node.store.tx_begin_read ()); + constexpr int max_attempts = 4; + + auto transaction = node.store.tx_begin_read (); + std::optional> hash_root; - for (auto i = 0; i < 4 && !hash_root; ++i) + + // Randomly select a block from ledger to request votes for + for (auto i = 0; i < max_attempts && !hash_root; ++i) { hash_root = node.ledger.hash_root_random (transaction); - if (node.active.recently_confirmed.exists (hash_root->first)) + + // Rebroadcasted votes for recently confirmed blocks might confuse the rep crawler + if (active.recently_confirmed.exists (hash_root->first)) { hash_root = std::nullopt; } } + if (!hash_root) { - return; + return std::nullopt; } + + // Don't send same block multiple times in tests + if (node.network_params.network.is_dev_network ()) { - nano::lock_guard lock{ active_mutex }; - // Don't send same block multiple times in tests - if (node.network_params.network.is_dev_network ()) + nano::lock_guard lock{ mutex }; + + for (auto i = 0; queries.get ().count (hash_root->first) != 0 && i < max_attempts; ++i) { - for (auto i (0); active.count (hash_root->first) != 0 && i < 4; ++i) - { - hash_root = node.ledger.hash_root_random (transaction); - } + hash_root = node.ledger.hash_root_random (transaction); } - active.insert (hash_root->first); - } - for (auto i (channels_a.begin ()), n (channels_a.end ()); i != n; ++i) - { - debug_assert (*i != nullptr); - on_rep_request (*i); - node.network.send_confirm_req (*i, *hash_root); } - // A representative must respond with a vote within the deadline - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [node_w, hash = hash_root->first] () { - if (auto node_l = node_w.lock ()) - { - auto target_finished_processed (node_l->vote_processor.total_processed + node_l->vote_processor.size ()); - node_l->rep_crawler.throttled_remove (hash, target_finished_processed); - } - }); + return hash_root; } -void nano::rep_crawler::query (std::shared_ptr const & channel_a) +bool nano::rep_crawler::track_rep_request (hash_root_t hash_root, std::shared_ptr const & channel) { - std::vector> peers; - peers.emplace_back (channel_a); - query (peers); -} + debug_assert (!mutex.try_lock ()); -void nano::rep_crawler::throttled_remove (nano::block_hash const & hash_a, uint64_t const target_finished_processed) -{ - if (node.vote_processor.total_processed >= target_finished_processed) + auto [_, inserted] = queries.emplace (query_entry{ hash_root.first, channel }); + if (!inserted) { - remove (hash_a); + return false; // Duplicate, not tracked } - else + + // Find and update the timestamp on all reps available on the endpoint (a single host may have multiple reps) + auto & index = reps.get (); + auto [begin, end] = index.equal_range (channel); + for (auto it = begin; it != end; ++it) { - std::weak_ptr node_w (node.shared ()); - node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [node_w, hash_a, target_finished_processed] () { - if (auto node_l = node_w.lock ()) - { - node_l->rep_crawler.throttled_remove (hash_a, target_finished_processed); - } + index.modify (it, [] (rep_entry & info) { + info.last_request = std::chrono::steady_clock::now (); }); } + + return true; } -bool nano::rep_crawler::is_pr (nano::transport::channel const & channel_a) const +void nano::rep_crawler::query (std::vector> const & target_channels) { - nano::lock_guard lock{ probable_reps_mutex }; - auto existing = probable_reps.get ().find (channel_a); - bool result = false; - if (existing != probable_reps.get ().end ()) + auto maybe_hash_root = prepare_query_target (); + if (!maybe_hash_root) { - result = node.ledger.weight (existing->account) > node.minimum_principal_weight (); + logger.debug (nano::log::type::rep_crawler, "No block to query"); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_target_failed); + return; } - return result; -} + auto hash_root = *maybe_hash_root; -bool nano::rep_crawler::response (std::shared_ptr const & channel_a, std::shared_ptr const & vote_a, bool force) -{ - bool error = true; - nano::lock_guard lock{ active_mutex }; - for (auto i = vote_a->hashes.begin (), n = vote_a->hashes.end (); i != n; ++i) + nano::lock_guard lock{ mutex }; + + for (const auto & channel : target_channels) { - if (force || active.count (*i) != 0) + debug_assert (channel != nullptr); + + bool tracked = track_rep_request (hash_root, channel); + if (tracked) + { + logger.debug (nano::log::type::rep_crawler, "Sending query for block {} to {}", hash_root.first.to_string (), channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_sent); + + auto const & [hash, root] = hash_root; + nano::confirm_req req{ network_constants, hash, root }; + + channel->send ( + req, + [this] (auto & ec, auto size) { + if (ec) + { + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::write_error, nano::stat::dir::out); + } + }, + nano::transport::buffer_drop_policy::no_socket_drop); + } + else { - responses.emplace_back (channel_a, vote_a); - error = false; - break; + logger.debug (nano::log::type::rep_crawler, "Ignoring duplicate query for block {} to {}", hash_root.first.to_string (), channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_duplicate); } } - return error; } -nano::uint128_t nano::rep_crawler::total_weight () const +void nano::rep_crawler::query (std::shared_ptr const & target_channel) { - nano::lock_guard lock{ probable_reps_mutex }; - nano::uint128_t result (0); - for (auto i (probable_reps.get ().begin ()), n (probable_reps.get ().end ()); i != n; ++i) + query (std::vector{ target_channel }); +} + +bool nano::rep_crawler::is_pr (std::shared_ptr const & channel) const +{ + nano::lock_guard lock{ mutex }; + auto existing = reps.get ().find (channel); + if (existing != reps.get ().end ()) { - if (i->channel->alive ()) - { - result += node.ledger.weight (i->account); - } + return node.ledger.weight (existing->account) >= node.minimum_principal_weight (); } - return result; + return false; } -void nano::rep_crawler::on_rep_request (std::shared_ptr const & channel_a) +bool nano::rep_crawler::process (std::shared_ptr const & vote, std::shared_ptr const & channel) { - nano::lock_guard lock{ probable_reps_mutex }; - if (channel_a->get_tcp_endpoint ().address () != boost::asio::ip::address_v6::any ()) + nano::lock_guard lock{ mutex }; + + auto & index = queries.get (); + auto [begin, end] = index.equal_range (channel); + for (auto it = begin; it != end; ++it) { - probably_rep_t::index::type & channel_ref_index = probable_reps.get (); + // TODO: This linear search could be slow, especially with large votes. + auto const target_hash = it->hash; + bool found = std::any_of (vote->hashes.begin (), vote->hashes.end (), [&target_hash] (nano::block_hash const & hash) { + return hash == target_hash; + }); - // Find and update the timestamp on all reps available on the endpoint (a single host may have multiple reps) - auto itr_pair = channel_ref_index.equal_range (*channel_a); - for (; itr_pair.first != itr_pair.second; itr_pair.first++) + if (found) { - channel_ref_index.modify (itr_pair.first, [] (nano::representative & value_a) { - value_a.last_request = std::chrono::steady_clock::now (); + logger.debug (nano::log::type::rep_crawler, "Processing response for block {} from {}", target_hash.to_string (), channel->to_string ()); + stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::response); + // TODO: Track query response time + + responses.push_back ({ channel, vote }); + queries.modify (it, [] (query_entry & e) { + e.replies++; }); + condition.notify_all (); + return true; // Found and processed } } + return false; } -void nano::rep_crawler::cleanup_reps () +nano::uint128_t nano::rep_crawler::total_weight () const { - std::vector> channels; + nano::lock_guard lock{ mutex }; + nano::uint128_t result = 0; + for (const auto & rep : reps) { - // Check known rep channels - nano::lock_guard lock{ probable_reps_mutex }; - auto iterator (probable_reps.get ().begin ()); - while (iterator != probable_reps.get ().end ()) + if (rep.channel->alive ()) { - if (iterator->channel->alive ()) - { - channels.push_back (iterator->channel); - ++iterator; - } - else - { - // Remove reps with closed channels - iterator = probable_reps.get ().erase (iterator); - } - } - } - // Remove reps with inactive channels - for (auto const & i : channels) - { - bool equal (false); - if (i->get_type () == nano::transport::transport_type::tcp) - { - auto find_channel (node.network.tcp_channels.find_channel (i->get_tcp_endpoint ())); - if (find_channel != nullptr && *find_channel == *static_cast (i.get ())) - { - equal = true; - } - } - else if (i->get_type () == nano::transport::transport_type::fake) - { - equal = true; - } - if (!equal) - { - nano::lock_guard lock{ probable_reps_mutex }; - probable_reps.get ().erase (*i); + result += node.ledger.weight (rep.account); } } + return result; } -std::vector nano::rep_crawler::representatives (std::size_t count_a, nano::uint128_t const weight_a, boost::optional const & opt_version_min_a) +std::vector nano::rep_crawler::representatives (std::size_t count, nano::uint128_t const minimum_weight, std::optional const & minimum_protocol_version) { - auto version_min (opt_version_min_a.value_or (node.network_params.network.protocol_version_min)); - std::multimap> ordered; - nano::lock_guard lock{ probable_reps_mutex }; - for (auto i (probable_reps.get ().begin ()), n (probable_reps.get ().end ()); i != n; ++i) + auto const version_min = minimum_protocol_version.value_or (node.network_params.network.protocol_version_min); + + nano::lock_guard lock{ mutex }; + + std::multimap> ordered; + for (const auto & rep : reps.get ()) { - auto weight = node.ledger.weight (i->account); - if (weight > weight_a && i->channel->get_network_version () >= version_min) + auto weight = node.ledger.weight (rep.account); + if (weight >= minimum_weight && rep.channel->get_network_version () >= version_min) { - ordered.insert ({ nano::amount{ weight }, *i }); + ordered.insert ({ nano::amount{ weight }, rep }); } } + std::vector result; - for (auto i = ordered.begin (), n = ordered.end (); i != n && result.size () < count_a; ++i) + for (auto const & [weight, rep] : ordered | std::views::take (count)) { - result.push_back (i->second); + result.push_back ({ rep.account, rep.channel }); } return result; } -std::vector nano::rep_crawler::principal_representatives (std::size_t count_a, boost::optional const & opt_version_min_a) +std::vector nano::rep_crawler::principal_representatives (std::size_t count, std::optional const & minimum_protocol_version) +{ + return representatives (count, node.minimum_principal_weight (), minimum_protocol_version); +} + +std::size_t nano::rep_crawler::representative_count () { - return representatives (count_a, node.minimum_principal_weight (), opt_version_min_a); + nano::lock_guard lock{ mutex }; + return reps.size (); } -std::vector> nano::rep_crawler::representative_endpoints (std::size_t count_a) +std::unique_ptr nano::rep_crawler::collect_container_info (const std::string & name) { - std::vector> result; - auto reps (representatives (count_a)); - for (auto const & rep : reps) + nano::lock_guard guard{ mutex }; + + auto composite = std::make_unique (name); + composite->add_component (std::make_unique (container_info{ "reps", reps.size (), sizeof (decltype (reps)::value_type) })); + composite->add_component (std::make_unique (container_info{ "queries", queries.size (), sizeof (decltype (queries)::value_type) })); + composite->add_component (std::make_unique (container_info{ "responses", responses.size (), sizeof (decltype (responses)::value_type) })); + return composite; +} + +// Only for tests +void nano::rep_crawler::force_add_rep (const nano::account & account, const std::shared_ptr & channel) +{ + release_assert (node.network_params.network.is_dev_network ()); + nano::lock_guard lock{ mutex }; + reps.emplace (rep_entry{ account, channel }); +} + +// Only for tests +void nano::rep_crawler::force_process (const std::shared_ptr & vote, const std::shared_ptr & channel) +{ + release_assert (node.network_params.network.is_dev_network ()); + nano::lock_guard lock{ mutex }; + responses.push_back ({ channel, vote }); +} + +// Only for tests +void nano::rep_crawler::force_query (const nano::block_hash & hash, const std::shared_ptr & channel) +{ + release_assert (node.network_params.network.is_dev_network ()); + nano::lock_guard lock{ mutex }; + queries.emplace (query_entry{ hash, channel }); +} + +/* + * rep_crawler_config + */ + +nano::rep_crawler_config::rep_crawler_config (nano::network_constants const & network_constants) +{ + if (network_constants.is_dev_network ()) { - result.push_back (rep.channel); + query_timeout = std::chrono::milliseconds{ 1000 }; } - return result; } -/** Total number of representatives */ -std::size_t nano::rep_crawler::representative_count () +nano::error nano::rep_crawler_config::serialize (nano::tomlconfig & toml) const { - nano::lock_guard lock{ probable_reps_mutex }; - return probable_reps.size (); + // TODO: Descriptions + toml.put ("query_timeout", query_timeout.count ()); + + return toml.get_error (); +} + +nano::error nano::rep_crawler_config::deserialize (nano::tomlconfig & toml) +{ + auto query_timeout_l = query_timeout.count (); + toml.get ("query_timeout", query_timeout_l); + query_timeout = std::chrono::milliseconds{ query_timeout_l }; + + return toml.get_error (); } diff --git a/nano/node/repcrawler.hpp b/nano/node/repcrawler.hpp index 70561df031..0855a7bdee 100644 --- a/nano/node/repcrawler.hpp +++ b/nano/node/repcrawler.hpp @@ -1,7 +1,10 @@ #pragma once +#include +#include #include +#include #include #include #include @@ -12,6 +15,7 @@ #include #include +#include #include namespace mi = boost::multi_index; @@ -19,31 +23,24 @@ namespace mi = boost::multi_index; namespace nano { class node; +class active_transactions; -/** - * A representative picked up during repcrawl. - */ -class representative +struct representative { -public: - representative () = default; - representative (nano::account account_a, std::shared_ptr const & channel_a) : - account (account_a), channel (channel_a) - { - debug_assert (channel != nullptr); - } - std::reference_wrapper channel_ref () const - { - return *channel; - }; - bool operator== (nano::representative const & other_a) const - { - return account == other_a.account; - } - nano::account account{}; + nano::account account; std::shared_ptr channel; - std::chrono::steady_clock::time_point last_request{ std::chrono::steady_clock::time_point () }; - std::chrono::steady_clock::time_point last_response{ std::chrono::steady_clock::time_point () }; +}; + +class rep_crawler_config final +{ +public: + explicit rep_crawler_config (nano::network_constants const &); + + nano::error deserialize (nano::tomlconfig & toml); + nano::error serialize (nano::tomlconfig & toml) const; + +public: + std::chrono::milliseconds query_timeout{ 1000 * 60 }; }; /** @@ -52,103 +49,142 @@ class representative */ class rep_crawler final { - friend std::unique_ptr collect_container_info (rep_crawler & rep_crawler, std::string const & name); - - // clang-format off - class tag_account {}; - class tag_channel_ref {}; - class tag_last_request {}; - class tag_sequenced {}; - - using probably_rep_t = boost::multi_index_container, mi::member>, - mi::sequenced>, - mi::ordered_non_unique, - mi::member>, - mi::hashed_non_unique, - mi::const_mem_fun, &representative::channel_ref>>>>; - // clang-format on - public: - rep_crawler (nano::node & node_a); + rep_crawler (rep_crawler_config const &, nano::node &); + ~rep_crawler (); - /** Start crawling */ void start (); + void stop (); - /** Remove block hash from list of active rep queries */ - void remove (nano::block_hash const &); - - /** Remove block hash from with delay depending on vote processor size */ - void throttled_remove (nano::block_hash const &, uint64_t const); + /** + * Called when a non-replay vote arrives that might be of interest to rep crawler. + * @return true, if the vote was of interest and was processed, this indicates that the rep is likely online and voting + */ + bool process (std::shared_ptr const &, std::shared_ptr const &); /** Attempt to determine if the peer manages one or more representative accounts */ - void query (std::vector> const & channels_a); + void query (std::vector> const & target_channels); /** Attempt to determine if the peer manages one or more representative accounts */ - void query (std::shared_ptr const & channel_a); + void query (std::shared_ptr const & target_channel); /** Query if a peer manages a principle representative */ - bool is_pr (nano::transport::channel const &) const; - - /** - * Called when a non-replay vote on a block previously sent by query() is received. This indicates - * with high probability that the endpoint is a representative node. - * The force flag can be set to skip the active check in unit testing when we want to force a vote in the rep crawler. - * @return false if any vote passed the checks and was added to the response queue of the rep crawler - */ - bool response (std::shared_ptr const &, std::shared_ptr const &, bool force = false); + bool is_pr (std::shared_ptr const &) const; /** Get total available weight from representatives */ nano::uint128_t total_weight () const; - /** Request a list of the top \p count_a known representatives in descending order of weight, with at least \p weight_a voting weight, and optionally with a minimum version \p opt_version_min_a */ - std::vector representatives (std::size_t count_a = std::numeric_limits::max (), nano::uint128_t const weight_a = 0, boost::optional const & opt_version_min_a = boost::none); - - /** Request a list of the top \p count_a known principal representatives in descending order of weight, optionally with a minimum version \p opt_version_min_a */ - std::vector principal_representatives (std::size_t count_a = std::numeric_limits::max (), boost::optional const & opt_version_min_a = boost::none); + /** Request a list of the top \p count known representatives in descending order of weight, with at least \p weight_a voting weight, and optionally with a minimum version \p minimum_protocol_version + */ + std::vector representatives (std::size_t count = std::numeric_limits::max (), nano::uint128_t minimum_weight = 0, std::optional const & minimum_protocol_version = {}); - /** Request a list of the top \p count_a known representative endpoints. */ - std::vector> representative_endpoints (std::size_t count_a); + /** Request a list of the top \p count known principal representatives in descending order of weight, optionally with a minimum version \p minimum_protocol_version + */ + std::vector principal_representatives (std::size_t count = std::numeric_limits::max (), std::optional const & minimum_protocol_version = {}); /** Total number of representatives */ std::size_t representative_count (); -private: + std::unique_ptr collect_container_info (std::string const & name); + +private: // Dependencies + rep_crawler_config const & config; nano::node & node; + nano::stats & stats; + nano::logger & logger; + nano::network_constants & network_constants; + nano::active_transactions & active; - /** Protects the active-hash container */ - nano::mutex active_mutex; +private: + void run (); + void cleanup (); + void validate_and_process (nano::unique_lock &); + bool query_predicate (bool sufficient_weight) const; + std::chrono::milliseconds query_interval (bool sufficient_weight) const; - /** We have solicted votes for these random blocks */ - std::unordered_set active; + using hash_root_t = std::pair; - // Validate responses to see if they're reps - void validate (); + /** Returns a list of endpoints to crawl. The total weight is passed in to avoid computing it twice. */ + std::vector> prepare_crawl_targets (bool sufficient_weight) const; + std::optional prepare_query_target (); + bool track_rep_request (hash_root_t hash_root, std::shared_ptr const & channel); - /** Called continuously to crawl for representatives */ - void ongoing_crawl (); +private: + /** + * A representative picked up during repcrawl. + */ + struct rep_entry + { + rep_entry (nano::account account_a, std::shared_ptr const & channel_a) : + account{ account_a }, + channel{ channel_a } + { + debug_assert (channel != nullptr); + } + + nano::account const account; + std::shared_ptr channel; + + std::chrono::steady_clock::time_point last_request{}; + std::chrono::steady_clock::time_point last_response{ std::chrono::steady_clock::now () }; + + nano::account get_account () const + { + return account; + } + }; - /** Returns a list of endpoints to crawl. The total weight is passed in to avoid computing it twice. */ - std::vector> get_crawl_targets (nano::uint128_t total_weight_a); + struct query_entry + { + nano::block_hash hash; + std::shared_ptr channel; + std::chrono::steady_clock::time_point time{ std::chrono::steady_clock::now () }; + unsigned int replies{ 0 }; // number of replies to the query + }; - /** When a rep request is made, this is called to update the last-request timestamp. */ - void on_rep_request (std::shared_ptr const & channel_a); + // clang-format off + class tag_hash {}; + class tag_account {}; + class tag_channel {}; + class tag_sequenced {}; - /** Clean representatives with inactive channels */ - void cleanup_reps (); + using ordered_reps = boost::multi_index_container, + mi::const_mem_fun>, + mi::sequenced>, + mi::hashed_non_unique, + mi::member, &rep_entry::channel>> + >>; - /** Protects the probable_reps container */ - mutable nano::mutex probable_reps_mutex; + using ordered_queries = boost::multi_index_container, + mi::member, &query_entry::channel>>, + mi::sequenced>, + mi::hashed_non_unique, + mi::member> + >>; + // clang-format on + + ordered_reps reps; + ordered_queries queries; + +private: + static size_t constexpr max_responses{ 1024 * 4 }; + using response_t = std::pair, std::shared_ptr>; + boost::circular_buffer responses{ max_responses }; - /** Probable representatives */ - probably_rep_t probable_reps; + std::chrono::steady_clock::time_point last_query{}; - friend class active_transactions_confirm_election_by_request_Test; - friend class active_transactions_confirm_frontier_Test; - friend class rep_crawler_local_Test; - friend class node_online_reps_rep_crawler_Test; + std::atomic stopped{ false }; + nano::condition_variable condition; + mutable nano::mutex mutex; + std::thread thread; - std::deque, std::shared_ptr>> responses; +public: // Testing + void force_add_rep (nano::account const & account, std::shared_ptr const & channel); + void force_process (std::shared_ptr const & vote, std::shared_ptr const & channel); + void force_query (nano::block_hash const & hash, std::shared_ptr const & channel); }; } diff --git a/nano/node/request_aggregator.cpp b/nano/node/request_aggregator.cpp index bb60519824..72a5e3e405 100644 --- a/nano/node/request_aggregator.cpp +++ b/nano/node/request_aggregator.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -14,15 +15,20 @@ nano::request_aggregator::request_aggregator (nano::node_config const & config_a max_delay (config_a.network_params.network.is_dev_network () ? 50 : 300), small_delay (config_a.network_params.network.is_dev_network () ? 10 : 50), max_channel_requests (config_a.max_queued_requests), + request_aggregator_threads (config_a.request_aggregator_threads), stats (stats_a), local_votes (history_a), ledger (ledger_a), wallets (wallets_a), active (active_a), generator (generator_a), - final_generator (final_generator_a), - thread ([this] () { run (); }) + final_generator (final_generator_a) { + for (auto i = 0; i < request_aggregator_threads; ++i) + { + threads.emplace_back ([this] () { run (); }); + } + generator.set_reply_action ([this] (std::shared_ptr const & vote_a, std::shared_ptr const & channel_a) { this->reply_action (vote_a, channel_a); }); @@ -131,9 +137,12 @@ void nano::request_aggregator::stop () stopped = true; } condition.notify_all (); - if (thread.joinable ()) + for (auto & thread : threads) { - thread.join (); + if (thread.joinable ()) + { + thread.join (); + } } } @@ -204,12 +213,12 @@ std::pair>, std::vector 1) { to_generate_final.push_back (block); - block = ledger.store.block.get (transaction, final_vote_hashes[1]); + block = ledger.block (transaction, final_vote_hashes[1]); debug_assert (final_vote_hashes.size () == 2); } } @@ -223,12 +232,12 @@ std::pair>, std::vectoraccount ().is_zero () ? block->sideband ().account : block->account (), confirmation_height_info); + ledger.store.confirmation_height.get (transaction, block->account (), confirmation_height_info); generate_final_vote = (confirmation_height_info.height >= block->sideband ().height); } } @@ -250,7 +259,7 @@ std::pair>, std::vector>, std::vectoraccount ().is_zero () ? block->sideband ().account : block->account (), confirmation_height_info); + ledger.store.confirmation_height.get (transaction, block->account (), confirmation_height_info); generate_final_vote = (confirmation_height_info.height >= block->sideband ().height); } } diff --git a/nano/node/request_aggregator.hpp b/nano/node/request_aggregator.hpp index 657b7b56f3..f88a6b4faa 100644 --- a/nano/node/request_aggregator.hpp +++ b/nano/node/request_aggregator.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace mi = boost::multi_index; @@ -74,6 +75,7 @@ class request_aggregator final std::chrono::milliseconds const max_delay; std::chrono::milliseconds const small_delay; std::size_t const max_channel_requests; + std::size_t const request_aggregator_threads; private: void run (); @@ -105,7 +107,7 @@ class request_aggregator final bool started{ false }; nano::condition_variable condition; nano::mutex mutex{ mutex_identifier (mutexes::request_aggregator) }; - std::thread thread; + std::vector threads; friend std::unique_ptr collect_container_info (request_aggregator &, std::string const &); }; diff --git a/nano/node/scheduler/hinted.cpp b/nano/node/scheduler/hinted.cpp index 1b9a8f688b..33e008fa53 100644 --- a/nano/node/scheduler/hinted.cpp +++ b/nano/node/scheduler/hinted.cpp @@ -2,6 +2,7 @@ #include #include #include +#include /* * hinted @@ -76,7 +77,7 @@ void nano::scheduler::hinted::activate (const nano::store::read_transaction & tr stack.pop (); // Check if block exists - if (auto block = node.store.block.get (transaction, current_hash); block) + if (auto block = node.ledger.block (transaction, current_hash); block) { // Ensure block is not already confirmed if (node.block_confirmed_or_being_confirmed (transaction, current_hash)) @@ -283,4 +284,4 @@ nano::error nano::scheduler::hinted_config::deserialize (nano::tomlconfig & toml } return toml.get_error (); -} \ No newline at end of file +} diff --git a/nano/node/scheduler/optimistic.cpp b/nano/node/scheduler/optimistic.cpp index bd5247957f..2c14251607 100644 --- a/nano/node/scheduler/optimistic.cpp +++ b/nano/node/scheduler/optimistic.cpp @@ -1,7 +1,9 @@ +#include #include #include #include #include +#include nano::scheduler::optimistic::optimistic (optimistic_config const & config_a, nano::node & node_a, nano::ledger & ledger_a, nano::active_transactions & active_a, nano::network_constants const & network_constants_a, nano::stats & stats_a) : config{ config_a }, diff --git a/nano/node/scheduler/optimistic.hpp b/nano/node/scheduler/optimistic.hpp index c590c8f17d..547bd7e8c1 100644 --- a/nano/node/scheduler/optimistic.hpp +++ b/nano/node/scheduler/optimistic.hpp @@ -22,9 +22,10 @@ namespace mi = boost::multi_index; namespace nano { -class node; -class ledger; +class account_info; class active_transactions; +class ledger; +class node; } namespace nano::scheduler diff --git a/nano/node/scheduler/priority.cpp b/nano/node/scheduler/priority.cpp index c75c5b0976..3fbaafda39 100644 --- a/nano/node/scheduler/priority.cpp +++ b/nano/node/scheduler/priority.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include nano::scheduler::priority::priority (nano::node & node_a, nano::stats & stats_a) : node{ node_a }, @@ -47,16 +49,25 @@ bool nano::scheduler::priority::activate (nano::account const & account_a, store { debug_assert (conf_info.frontier != info->head); auto hash = conf_info.height == 0 ? info->open_block : node.store.block.successor (transaction, conf_info.frontier); - auto block = node.store.block.get (transaction, hash); + auto block = node.ledger.block (transaction, hash); debug_assert (block != nullptr); if (node.ledger.dependents_confirmed (transaction, *block)) { - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated); - auto balance = node.ledger.balance (transaction, hash); - auto previous_balance = node.ledger.balance (transaction, conf_info.frontier); + auto const balance = node.ledger.balance (transaction, hash).value (); + auto const previous_balance = node.ledger.balance (transaction, conf_info.frontier).value_or (0); + auto const balance_priority = std::max (balance, previous_balance); + + node.stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated); + node.logger.trace (nano::log::type::election_scheduler, nano::log::detail::block_activated, + nano::log::arg{ "account", account_a.to_account () }, // TODO: Convert to lazy eval + nano::log::arg{ "block", block }, + nano::log::arg{ "time", info->modified }, + nano::log::arg{ "priority", balance_priority }); + nano::lock_guard lock{ mutex }; - buckets->push (info->modified, block, std::max (balance, previous_balance)); + buckets->push (info->modified, block, balance_priority); notify (); + return true; // Activated } } diff --git a/nano/node/telemetry.cpp b/nano/node/telemetry.cpp index 5260fbfa0c..5e5b15fd2f 100644 --- a/nano/node/telemetry.cpp +++ b/nano/node/telemetry.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -242,7 +243,7 @@ void nano::telemetry::cleanup () { debug_assert (!mutex.try_lock ()); - nano::erase_if (telemetries, [this] (entry const & entry) { + erase_if (telemetries, [this] (entry const & entry) { // Remove if telemetry data is stale if (!check_timeout (entry)) { @@ -439,4 +440,4 @@ nano::telemetry_data nano::consolidate_telemetry_data (std::vector (version_fragments[4]); return consolidated_data; -} \ No newline at end of file +} diff --git a/nano/node/transport/channel.cpp b/nano/node/transport/channel.cpp index 39037b734b..15b6e4acf9 100644 --- a/nano/node/transport/channel.cpp +++ b/nano/node/transport/channel.cpp @@ -16,14 +16,21 @@ nano::transport::channel::channel (nano::node & node_a) : void nano::transport::channel::send (nano::message & message_a, std::function const & callback_a, nano::transport::buffer_drop_policy drop_policy_a, nano::transport::traffic_type traffic_type) { - auto buffer (message_a.to_shared_const_buffer ()); - auto detail = nano::to_stat_detail (message_a.header.type); - auto is_droppable_by_limiter = (drop_policy_a == nano::transport::buffer_drop_policy::limiter); - auto should_pass (node.outbound_limiter.should_pass (buffer.size (), to_bandwidth_limit_type (traffic_type))); - if (!is_droppable_by_limiter || should_pass) + auto buffer = message_a.to_shared_const_buffer (); + + bool is_droppable_by_limiter = (drop_policy_a == nano::transport::buffer_drop_policy::limiter); + bool should_pass = node.outbound_limiter.should_pass (buffer.size (), to_bandwidth_limit_type (traffic_type)); + bool pass = !is_droppable_by_limiter || should_pass; + + node.stats.inc (pass ? nano::stat::type::message : nano::stat::type::drop, to_stat_detail (message_a.type ()), nano::stat::dir::out); + node.logger.trace (nano::log::type::channel_sent, to_log_detail (message_a.type ()), + nano::log::arg{ "message", message_a }, + nano::log::arg{ "channel", *this }, + nano::log::arg{ "dropped", !pass }); + + if (pass) { send_buffer (buffer, callback_a, drop_policy_a, traffic_type); - node.stats.inc (nano::stat::type::message, detail, nano::stat::dir::out); } else { @@ -33,12 +40,6 @@ void nano::transport::channel::send (nano::message & message_a, std::function +#include #include #include #include @@ -140,6 +141,9 @@ class channel protected: nano::node & node; + +public: // Logging + virtual void operator() (nano::object_stream &) const; }; } @@ -183,4 +187,4 @@ struct hash> return hash (channel_a.get ()); } }; -} \ No newline at end of file +} diff --git a/nano/node/transport/inproc.cpp b/nano/node/transport/inproc.cpp index a015a2fdbc..b07bd0d35f 100644 --- a/nano/node/transport/inproc.cpp +++ b/nano/node/transport/inproc.cpp @@ -78,7 +78,7 @@ void nano::transport::inproc::channel::send_buffer (nano::shared_const_buffer co // process message { - node.stats.inc (nano::stat::type::message, nano::to_stat_detail (message_a->header.type), nano::stat::dir::in); + node.stats.inc (nano::stat::type::message, to_stat_detail (message_a->header.type), nano::stat::dir::in); // create an inbound message visitor class to handle incoming messages message_visitor_inbound visitor{ destination.network.inbound, remote_channel }; diff --git a/nano/node/transport/message_deserializer.cpp b/nano/node/transport/message_deserializer.cpp index 238e74f9aa..174a875eb7 100644 --- a/nano/node/transport/message_deserializer.cpp +++ b/nano/node/transport/message_deserializer.cpp @@ -1,6 +1,8 @@ #include #include +#include + nano::transport::message_deserializer::message_deserializer (nano::network_constants const & network_constants_a, nano::network_filter & publish_filter_a, nano::block_uniquer & block_uniquer_a, nano::vote_uniquer & vote_uniquer_a, read_query read_op) : read_buffer{ std::make_shared> () }, @@ -380,143 +382,14 @@ std::unique_ptr nano::transport::message_deserializer::deser return {}; } -nano::stat::detail nano::transport::message_deserializer::to_stat_detail (parse_status status) +nano::stat::detail nano::transport::to_stat_detail (nano::transport::parse_status status) { - // Keep additional `break` for readability - switch (status) - { - case parse_status::none: - case parse_status::success: - break; - case parse_status::insufficient_work: - return stat::detail::insufficient_work; - break; - case parse_status::invalid_header: - return stat::detail::invalid_header; - break; - case parse_status::invalid_message_type: - return stat::detail::invalid_message_type; - break; - case parse_status::invalid_keepalive_message: - return stat::detail::invalid_keepalive_message; - break; - case parse_status::invalid_publish_message: - return stat::detail::invalid_publish_message; - break; - case parse_status::invalid_confirm_req_message: - return stat::detail::invalid_confirm_req_message; - break; - case parse_status::invalid_confirm_ack_message: - return stat::detail::invalid_confirm_ack_message; - break; - case parse_status::invalid_node_id_handshake_message: - return stat::detail::invalid_node_id_handshake_message; - break; - case parse_status::invalid_telemetry_req_message: - return stat::detail::invalid_telemetry_req_message; - break; - case parse_status::invalid_telemetry_ack_message: - return stat::detail::invalid_telemetry_ack_message; - break; - case parse_status::invalid_bulk_pull_message: - return stat::detail::invalid_bulk_pull_message; - break; - case parse_status::invalid_bulk_pull_account_message: - return stat::detail::invalid_bulk_pull_account_message; - break; - case parse_status::invalid_frontier_req_message: - return stat::detail::invalid_frontier_req_message; - break; - case parse_status::invalid_asc_pull_req_message: - return stat::detail::invalid_asc_pull_req_message; - break; - case parse_status::invalid_asc_pull_ack_message: - return stat::detail::invalid_asc_pull_ack_message; - break; - case parse_status::invalid_network: - return stat::detail::invalid_network; - break; - case parse_status::outdated_version: - return stat::detail::outdated_version; - break; - case parse_status::duplicate_publish_message: - return stat::detail::duplicate_publish; - break; - case parse_status::message_size_too_big: - return stat::detail::message_too_big; - break; - } - return {}; + auto value = magic_enum::enum_cast (magic_enum::enum_name (status)); + debug_assert (value); + return value.value_or (nano::stat::detail{}); } -std::string nano::transport::message_deserializer::to_string (parse_status status) +std::string_view nano::transport::to_string (nano::transport::parse_status status) { - // Keep additional `break` for readability - switch (status) - { - case parse_status::none: - return "none"; - break; - case parse_status::success: - return "success"; - break; - case parse_status::insufficient_work: - return "insufficient_work"; - break; - case parse_status::invalid_header: - return "invalid_header"; - break; - case parse_status::invalid_message_type: - return "invalid_message_type"; - break; - case parse_status::invalid_keepalive_message: - return "invalid_keepalive_message"; - break; - case parse_status::invalid_publish_message: - return "invalid_publish_message"; - break; - case parse_status::invalid_confirm_req_message: - return "invalid_confirm_req_message"; - break; - case parse_status::invalid_confirm_ack_message: - return "invalid_confirm_ack_message"; - break; - case parse_status::invalid_node_id_handshake_message: - return "invalid_node_id_handshake_message"; - break; - case parse_status::invalid_telemetry_req_message: - return "invalid_telemetry_req_message"; - break; - case parse_status::invalid_telemetry_ack_message: - return "invalid_telemetry_ack_message"; - break; - case parse_status::invalid_bulk_pull_message: - return "invalid_bulk_pull_message"; - break; - case parse_status::invalid_bulk_pull_account_message: - return "invalid_bulk_pull_account_message"; - break; - case parse_status::invalid_frontier_req_message: - return "invalid_frontier_req_message"; - break; - case parse_status::invalid_asc_pull_req_message: - return "invalid_asc_pull_req_message"; - break; - case parse_status::invalid_asc_pull_ack_message: - return "invalid_asc_pull_ack_message"; - break; - case parse_status::invalid_network: - return "invalid_network"; - break; - case parse_status::outdated_version: - return "outdated_version"; - break; - case parse_status::duplicate_publish_message: - return "duplicate_publish_message"; - break; - case parse_status::message_size_too_big: - return "message_size_too_big"; - break; - } - return "n/a"; + return magic_enum::enum_name (status); } diff --git a/nano/node/transport/message_deserializer.hpp b/nano/node/transport/message_deserializer.hpp index 0a85454e51..c5ac4346b9 100644 --- a/nano/node/transport/message_deserializer.hpp +++ b/nano/node/transport/message_deserializer.hpp @@ -10,34 +10,34 @@ namespace nano { namespace transport { + enum class parse_status + { + none, + success, + insufficient_work, + invalid_header, + invalid_message_type, + invalid_keepalive_message, + invalid_publish_message, + invalid_confirm_req_message, + invalid_confirm_ack_message, + invalid_node_id_handshake_message, + invalid_telemetry_req_message, + invalid_telemetry_ack_message, + invalid_bulk_pull_message, + invalid_bulk_pull_account_message, + invalid_frontier_req_message, + invalid_asc_pull_req_message, + invalid_asc_pull_ack_message, + invalid_network, + outdated_version, + duplicate_publish_message, + message_size_too_big, + }; + class message_deserializer : public std::enable_shared_from_this { public: - enum class parse_status - { - none, - success, - insufficient_work, - invalid_header, - invalid_message_type, - invalid_keepalive_message, - invalid_publish_message, - invalid_confirm_req_message, - invalid_confirm_ack_message, - invalid_node_id_handshake_message, - invalid_telemetry_req_message, - invalid_telemetry_ack_message, - invalid_bulk_pull_message, - invalid_bulk_pull_account_message, - invalid_frontier_req_message, - invalid_asc_pull_req_message, - invalid_asc_pull_ack_message, - invalid_network, - outdated_version, - duplicate_publish_message, - message_size_too_big, - }; - using callback_type = std::function)>; parse_status status; @@ -89,11 +89,9 @@ namespace transport nano::block_uniquer & block_uniquer_m; nano::vote_uniquer & vote_uniquer_m; read_query read_op; - - public: - static stat::detail to_stat_detail (parse_status); - static std::string to_string (parse_status); }; + nano::stat::detail to_stat_detail (parse_status); + std::string_view to_string (parse_status); } } diff --git a/nano/node/transport/socket.cpp b/nano/node/transport/socket.cpp index 21fbc4de44..4271905534 100644 --- a/nano/node/transport/socket.cpp +++ b/nano/node/transport/socket.cpp @@ -13,6 +13,8 @@ #include #include +#include + /* * socket */ @@ -54,6 +56,7 @@ void nano::transport::socket::async_connect (nano::tcp_endpoint const & endpoint this_l->tcp_socket.async_connect (endpoint_a, boost::asio::bind_executor (this_l->strand, [this_l, callback = std::move (callback_a), endpoint_a] (boost::system::error_code const & ec) { + this_l->remote = endpoint_a; if (ec) { this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_connect_error, nano::stat::dir::in); @@ -62,9 +65,13 @@ void nano::transport::socket::async_connect (nano::tcp_endpoint const & endpoint else { this_l->set_last_completion (); + { + // Best effort attempt to get endpoint address + boost::system::error_code ec; + this_l->local = this_l->tcp_socket.local_endpoint (ec); + } + this_l->node.observers.socket_connected.notify (*this_l); } - this_l->remote = endpoint_a; - this_l->node.observers.socket_connected.notify (*this_l); callback (ec); })); } @@ -241,23 +248,22 @@ void nano::transport::socket::ongoing_checkup () if (this_l->endpoint_type () == endpoint_type_t::server && (now - this_l->last_receive_time_or_init) > static_cast (this_l->silent_connection_tolerance_time.count ())) { this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_silent_connection_drop, nano::stat::dir::in); + condition_to_disconnect = true; } // if there is no activity for timeout seconds then disconnect if ((now - this_l->last_completion_time_or_init) > this_l->timeout) { - this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_io_timeout_drop, - this_l->endpoint_type () == endpoint_type_t::server ? nano::stat::dir::in : nano::stat::dir::out); + this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_io_timeout_drop, this_l->endpoint_type () == endpoint_type_t::server ? nano::stat::dir::in : nano::stat::dir::out); + condition_to_disconnect = true; } if (condition_to_disconnect) { - if (this_l->node.config.logging.network_timeout_logging ()) - { - this_l->node.logger.try_log (boost::str (boost::format ("Disconnecting from %1% due to timeout") % this_l->remote)); - } + this_l->node.logger.debug (nano::log::type::tcp_server, "Closing socket due to timeout ({})", nano::util::to_str (this_l->remote)); + this_l->timed_out = true; this_l->close (); } @@ -330,19 +336,29 @@ void nano::transport::socket::close_internal () if (ec) { - node.logger.try_log ("Failed to close socket gracefully: ", ec.message ()); - node.stats.inc (nano::stat::type::bootstrap, nano::stat::detail::error_socket_close); + node.stats.inc (nano::stat::type::socket, nano::stat::detail::error_socket_close); + node.logger.error (nano::log::type::socket, "Failed to close socket gracefully: {} ({})", ec.message (), nano::util::to_str (remote)); } } nano::tcp_endpoint nano::transport::socket::remote_endpoint () const { + // Using cached value to avoid calling tcp_socket.remote_endpoint() which may be invalid (throw) after closing the socket return remote; } nano::tcp_endpoint nano::transport::socket::local_endpoint () const { - return tcp_socket.local_endpoint (); + // Using cached value to avoid calling tcp_socket.local_endpoint() which may be invalid (throw) after closing the socket + return local; +} + +void nano::transport::socket::operator() (nano::object_stream & obs) const +{ + obs.write ("remote_endpoint", remote_endpoint ()); + obs.write ("local_endpoint", local_endpoint ()); + obs.write ("type", type_m); + obs.write ("endpoint_type", endpoint_type_m); } /* @@ -452,18 +468,7 @@ std::size_t network_prefix) return counted_connections; } -std::string nano::transport::socket_type_to_string (nano::transport::socket::type_t type) +std::string_view nano::transport::to_string (nano::transport::socket::type_t type) { - switch (type) - { - case nano::transport::socket::type_t::undefined: - return "undefined"; - case nano::transport::socket::type_t::bootstrap: - return "bootstrap"; - case nano::transport::socket::type_t::realtime: - return "realtime"; - case nano::transport::socket::type_t::realtime_response_server: - return "realtime_response_server"; - } - return "n/a"; + return magic_enum::enum_name (type); } diff --git a/nano/node/transport/socket.hpp b/nano/node/transport/socket.hpp index b2593b1ba2..91f7d008fc 100644 --- a/nano/node/transport/socket.hpp +++ b/nano/node/transport/socket.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -157,6 +158,7 @@ class socket final : public std::enable_shared_from_this>; diff --git a/nano/node/transport/tcp.cpp b/nano/node/transport/tcp.cpp index 543b13b5ea..e6ddca6120 100644 --- a/nano/node/transport/tcp.cpp +++ b/nano/node/transport/tcp.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -98,7 +99,7 @@ void nano::transport::channel_tcp::send_buffer (nano::shared_const_buffer const std::string nano::transport::channel_tcp::to_string () const { - return boost::str (boost::format ("%1%") % get_tcp_endpoint ()); + return nano::util::to_str (get_tcp_endpoint ()); } void nano::transport::channel_tcp::set_endpoint () @@ -112,6 +113,13 @@ void nano::transport::channel_tcp::set_endpoint () } } +void nano::transport::channel_tcp::operator() (nano::object_stream & obs) const +{ + nano::transport::channel::operator() (obs); // Write common data + + obs.write ("socket", socket); +} + /* * tcp_channels */ @@ -349,6 +357,7 @@ void nano::transport::tcp_channels::process_message (nano::message const & messa void nano::transport::tcp_channels::start () { ongoing_keepalive (); + ongoing_merge (0); } void nano::transport::tcp_channels::stop () @@ -456,13 +465,9 @@ void nano::transport::tcp_channels::purge (std::chrono::steady_clock::time_point nano::lock_guard lock{ mutex }; // Remove channels with dead underlying sockets - for (auto it = channels.begin (); it != channels.end (); ++it) - { - if (!it->socket->alive ()) - { - it = channels.erase (it); - } - } + erase_if (channels, [] (auto const & entry) { + return !entry.channel->alive (); + }); auto disconnect_cutoff (channels.get ().lower_bound (cutoff_a)); channels.get ().erase (channels.get ().begin (), disconnect_cutoff); @@ -505,6 +510,77 @@ void nano::transport::tcp_channels::ongoing_keepalive () }); } +void nano::transport::tcp_channels::ongoing_merge (size_t channel_index) +{ + nano::unique_lock lock{ mutex }; + std::optional keepalive; + size_t count = 0; + while (!keepalive && channels.size () > 0 && count++ < channels.size ()) + { + ++channel_index; + if (channels.size () <= channel_index) + { + channel_index = 0; + } + auto server = channels.get ()[channel_index].response_server; + if (server && server->last_keepalive) + { + keepalive = std::move (server->last_keepalive); + server->last_keepalive = std::nullopt; + } + } + lock.unlock (); + if (keepalive) + { + ongoing_merge (channel_index, *keepalive, 1); + } + else + { + std::weak_ptr node_w = node.shared (); + node.workers.add_timed_task (std::chrono::steady_clock::now () + node.network_params.network.merge_period, [node_w, channel_index] () { + if (auto node_l = node_w.lock ()) + { + if (!node_l->network.tcp_channels.stopped) + { + node_l->network.tcp_channels.ongoing_merge (channel_index); + } + } + }); + } +} + +void nano::transport::tcp_channels::ongoing_merge (size_t channel_index, nano::keepalive keepalive, size_t peer_index) +{ + debug_assert (peer_index < keepalive.peers.size ()); + node.network.merge_peer (keepalive.peers[peer_index++]); + if (peer_index < keepalive.peers.size ()) + { + std::weak_ptr node_w = node.shared (); + node.workers.add_timed_task (std::chrono::steady_clock::now () + node.network_params.network.merge_period, [node_w, channel_index, keepalive, peer_index] () { + if (auto node_l = node_w.lock ()) + { + if (!node_l->network.tcp_channels.stopped) + { + node_l->network.tcp_channels.ongoing_merge (channel_index, keepalive, peer_index); + } + } + }); + } + else + { + std::weak_ptr node_w = node.shared (); + node.workers.add_timed_task (std::chrono::steady_clock::now () + node.network_params.network.merge_period, [node_w, channel_index] () { + if (auto node_l = node_w.lock ()) + { + if (!node_l->network.tcp_channels.stopped) + { + node_l->network.tcp_channels.ongoing_merge (channel_index); + } + } + }); + } +} + void nano::transport::tcp_channels::list (std::deque> & deque_a, uint8_t minimum_version_a, bool include_temporary_channels_a) { nano::lock_guard lock{ mutex }; @@ -555,10 +631,9 @@ void nano::transport::tcp_channels::start_tcp (nano::endpoint const & endpoint_a auto query = node_l->network.prepare_handshake_query (endpoint_a); nano::node_id_handshake message{ node_l->network_params.network, query }; - if (node_l->config.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Node ID handshake request sent with node ID %1% to %2%: query %3%") % node_l->node_id.pub.to_node_id () % endpoint_a % (query ? query->cookie.to_string () : "not set"))); - } + node_l->logger.debug (nano::log::type::tcp, "Handshake sent to: {} (query: {})", + nano::util::to_str (endpoint_a), + (query ? query->cookie.to_string () : "")); channel->set_endpoint (); std::shared_ptr> receive_buffer (std::make_shared> ()); @@ -572,30 +647,25 @@ void nano::transport::tcp_channels::start_tcp (nano::endpoint const & endpoint_a } else { + node_l->logger.debug (nano::log::type::tcp, "Error sending handshake to: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + if (auto socket_l = channel->socket.lock ()) { socket_l->close (); } - if (node_l->config.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Error sending node_id_handshake to %1%: %2%") % endpoint_a % ec.message ())); - } } } }); } else { - if (node_l->config.logging.network_logging ()) + if (ec) { - if (ec) - { - node_l->logger.try_log (boost::str (boost::format ("Error connecting to %1%: %2%") % endpoint_a % ec.message ())); - } - else - { - node_l->logger.try_log (boost::str (boost::format ("Error connecting to %1%") % endpoint_a)); - } + node_l->logger.debug (nano::log::type::tcp, "Error connecting to: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + } + else + { + node_l->logger.debug (nano::log::type::tcp, "Error connecting to: {}", nano::util::to_str (endpoint_a)); } } } @@ -633,10 +703,8 @@ void nano::transport::tcp_channels::start_tcp_receive_node_id (std::shared_ptrconfig.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Error reading node_id_handshake from %1%: %2%") % endpoint_a % ec.message ())); - } + node_l->logger.debug (nano::log::type::tcp, "Error reading handshake from: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + cleanup_node_id_handshake_socket (endpoint_a); return; } @@ -646,10 +714,8 @@ void nano::transport::tcp_channels::start_tcp_receive_node_id (std::shared_ptrtype () != nano::message_type::node_id_handshake) { - if (node_l->config.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Error reading node_id_handshake message header from %1%") % endpoint_a)); - } + node_l->logger.debug (nano::log::type::tcp, "Error reading handshake header from: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + cleanup_node_id_handshake_socket (endpoint_a); return; } @@ -678,10 +744,8 @@ void nano::transport::tcp_channels::start_tcp_receive_node_id (std::shared_ptrconfig.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Error reading node_id_handshake from %1%") % endpoint_a)); - } + node_l->logger.debug (nano::log::type::tcp, "Error reading handshake payload from: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + cleanup_node_id_handshake_socket (endpoint_a); return; } @@ -714,10 +778,9 @@ void nano::transport::tcp_channels::start_tcp_receive_node_id (std::shared_ptrnetwork.prepare_handshake_response (*handshake.query, handshake.is_v2 ()); nano::node_id_handshake handshake_response (node_l->network_params.network, std::nullopt, response); - if (node_l->config.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Node ID handshake response sent with node ID %1% to %2%: query %3%") % node_l->node_id.pub.to_node_id () % endpoint_a % handshake.query->cookie.to_string ())); - } + node_l->logger.debug (nano::log::type::tcp, "Handshake response sent to {} (query: {})", + nano::util::to_str (endpoint_a), + handshake.query->cookie.to_string ()); channel_a->send (handshake_response, [node_w, channel_a, endpoint_a, cleanup_node_id_handshake_socket] (boost::system::error_code const & ec, std::size_t size_a) { auto node_l = node_w.lock (); @@ -727,10 +790,8 @@ void nano::transport::tcp_channels::start_tcp_receive_node_id (std::shared_ptrconfig.logging.network_node_id_handshake_logging ()) - { - node_l->logger.try_log (boost::str (boost::format ("Error sending node_id_handshake to %1%: %2%") % endpoint_a % ec.message ())); - } + node_l->logger.debug (nano::log::type::tcp, "Error sending handshake response to: {} ({})", nano::util::to_str (endpoint_a), ec.message ()); + cleanup_node_id_handshake_socket (endpoint_a); return; } diff --git a/nano/node/transport/tcp.hpp b/nano/node/transport/tcp.hpp index 80196a3089..0f65b3bd0e 100644 --- a/nano/node/transport/tcp.hpp +++ b/nano/node/transport/tcp.hpp @@ -93,7 +93,11 @@ namespace transport private: nano::tcp_endpoint endpoint{ boost::asio::ip::address_v6::any (), 0 }; + + public: // Logging + void operator() (nano::object_stream &) const override; }; + class tcp_channels final { friend class nano::transport::channel_tcp; @@ -124,6 +128,8 @@ namespace transport std::unique_ptr collect_container_info (std::string const &); void purge (std::chrono::steady_clock::time_point const &); void ongoing_keepalive (); + void ongoing_merge (size_t channel_index); + void ongoing_merge (size_t channel_index, nano::keepalive keepalive, size_t peer_index); void list (std::deque> &, uint8_t = 0, bool = true); void modify (std::shared_ptr const &, std::function const &)>); void update (nano::tcp_endpoint const &); diff --git a/nano/node/transport/tcp_server.cpp b/nano/node/transport/tcp_server.cpp index 57222dc365..7e37ef97bc 100644 --- a/nano/node/transport/tcp_server.cpp +++ b/nano/node/transport/tcp_server.cpp @@ -56,7 +56,7 @@ void nano::transport::tcp_listener::start (std::functionacceptor.is_open ()) { - this_l->node.logger.always_log ("Network: Acceptor is not open"); + this_l->node.logger.error (nano::log::type::tcp_listener, "Acceptor is not open"); return; } @@ -138,20 +138,18 @@ void nano::transport::tcp_listener::on_connection (std::functionconnections_per_address.size () >= this_l->max_inbound_connections) { - this_l->node.logger.try_log ("Network: max_inbound_connections reached, unable to open new connection"); this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_accept_failure, nano::stat::dir::in); + this_l->node.logger.debug (nano::log::type::tcp_listener, "Max connections reached ({}), unable to open new connection", this_l->connections_per_address.size ()); + this_l->on_connection_requeue_delayed (std::move (cbk)); return; } if (this_l->limit_reached_for_incoming_ip_connections (new_connection)) { - auto const remote_ip_address = new_connection->remote_endpoint ().address (); - auto const log_message = boost::str ( - boost::format ("Network: max connections per IP (max_peers_per_ip) was reached for %1%, unable to open new connection") - % remote_ip_address.to_string ()); - this_l->node.logger.try_log (log_message); this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_max_per_ip, nano::stat::dir::in); + this_l->node.logger.debug (nano::log::type::tcp_listener, "Max connections per IP reached ({}), unable to open new connection", new_connection->remote_endpoint ().address ().to_string ()); + this_l->on_connection_requeue_delayed (std::move (cbk)); return; } @@ -161,18 +159,24 @@ void nano::transport::tcp_listener::on_connection (std::functionremote_endpoint ().address (); debug_assert (remote_ip_address.is_v6 ()); auto const remote_subnet = socket_functions::get_ipv6_subnet_address (remote_ip_address.to_v6 (), this_l->node.network_params.network.max_peers_per_subnetwork); - auto const log_message = boost::str ( - boost::format ("Network: max connections per subnetwork (max_peers_per_subnetwork) was reached for subnetwork %1% (remote IP: %2%), unable to open new connection") - % remote_subnet.canonical ().to_string () - % remote_ip_address.to_string ()); - this_l->node.logger.try_log (log_message); + this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_max_per_subnetwork, nano::stat::dir::in); + this_l->node.logger.debug (nano::log::type::tcp_listener, "Max connections per subnetwork reached (subnetwork: {}, ip: {}), unable to open new connection", + remote_subnet.canonical ().to_string (), + remote_ip_address.to_string ()); + this_l->on_connection_requeue_delayed (std::move (cbk)); return; } if (!ec_a) { + { + // Best effort attempt to get endpoint addresses + boost::system::error_code ec; + new_connection->local = new_connection->tcp_socket.local_endpoint (ec); + } + // Make sure the new connection doesn't idle. Note that in most cases, the callback is going to start // an IO operation immediately, which will start a timer. new_connection->start (); @@ -185,13 +189,13 @@ void nano::transport::tcp_listener::on_connection (std::functionon_connection (std::move (cbk)); return; } - this_l->node.logger.always_log ("Network: Stopping to accept connections"); + this_l->node.logger.warn (nano::log::type::tcp_listener, "Stopping to accept new connections"); return; } // accept error - this_l->node.logger.try_log ("Network: Unable to accept connection: ", ec_a.message ()); this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_accept_failure, nano::stat::dir::in); + this_l->node.logger.error (nano::log::type::tcp_listener, "Unable to accept connection: {} ({})", ec_a.message (), new_connection->remote_endpoint ().address ().to_string ()); if (is_temporary_error (ec_a)) { @@ -208,7 +212,7 @@ void nano::transport::tcp_listener::on_connection (std::functionnode.logger.always_log ("Network: Stopping to accept connections"); + this_l->node.logger.warn (nano::log::type::tcp_listener, "Stopping to accept new connections"); })); })); } @@ -227,15 +231,10 @@ void nano::transport::tcp_listener::on_connection_requeue_delayed (std::function void nano::transport::tcp_listener::evict_dead_connections () { debug_assert (strand.running_in_this_thread ()); - for (auto it = connections_per_address.begin (); it != connections_per_address.end ();) - { - if (it->second.expired ()) - { - it = connections_per_address.erase (it); - continue; - } - ++it; - } + + erase_if (connections_per_address, [] (auto const & entry) { + return entry.second.expired (); + }); } void nano::transport::tcp_listener::accept_action (boost::system::error_code const & ec, std::shared_ptr const & socket_a) @@ -250,10 +249,7 @@ void nano::transport::tcp_listener::accept_action (boost::system::error_code con else { node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_excluded); - if (node.config.logging.network_rejected_logging ()) - { - node.logger.try_log ("Rejected connection from excluded peer ", socket_a->remote_endpoint ()); - } + node.logger.debug (nano::log::type::tcp_server, "Rejected connection from excluded peer: {}", nano::util::to_str (socket_a->remote_endpoint ())); } } @@ -304,10 +300,8 @@ nano::transport::tcp_server::~tcp_server () { return; } - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Exiting incoming TCP/bootstrap server"); - } + + node->logger.debug (nano::log::type::tcp_server, "Exiting TCP server ({})", nano::util::to_str (remote_endpoint)); if (socket->type () == nano::transport::socket::type_t::bootstrap) { @@ -340,6 +334,12 @@ void nano::transport::tcp_server::start () remote_endpoint = socket->remote_endpoint (); debug_assert (remote_endpoint.port () != 0); } + + if (auto node_l = node.lock (); node_l) + { + node_l->logger.debug (nano::log::type::tcp_server, "Starting TCP server ({})", nano::util::to_str (remote_endpoint)); + } + receive_message (); } @@ -367,7 +367,12 @@ void nano::transport::tcp_server::receive_message () if (ec) { // IO error or critical error when deserializing message - node->stats.inc (nano::stat::type::error, nano::transport::message_deserializer::to_stat_detail (this_l->message_deserializer->status)); + node->stats.inc (nano::stat::type::error, to_stat_detail (this_l->message_deserializer->status)); + node->logger.debug (nano::log::type::tcp_server, "Error reading message: {}, status: {} ({})", + ec.message (), + to_string (this_l->message_deserializer->status), + nano::util::to_str (this_l->remote_endpoint)); + this_l->stop (); } else @@ -392,11 +397,19 @@ void nano::transport::tcp_server::received_message (std::unique_ptrstatus != transport::message_deserializer::parse_status::success); - node->stats.inc (nano::stat::type::error, nano::transport::message_deserializer::to_stat_detail (message_deserializer->status)); - if (message_deserializer->status == transport::message_deserializer::parse_status::duplicate_publish_message) + debug_assert (message_deserializer->status != transport::parse_status::success); + + node->stats.inc (nano::stat::type::error, to_stat_detail (message_deserializer->status)); + if (message_deserializer->status == transport::parse_status::duplicate_publish_message) { - node->stats.inc (nano::stat::type::filter, nano::stat::detail::duplicate_publish); + node->stats.inc (nano::stat::type::filter, nano::stat::detail::duplicate_publish_message); + } + else + { + // Avoid too much noise about `duplicate_publish_message` errors + node->logger.debug (nano::log::type::tcp_server, "Error deserializing message: {} ({})", + to_string (message_deserializer->status), + nano::util::to_str (remote_endpoint)); } } @@ -413,7 +426,7 @@ bool nano::transport::tcp_server::process_message (std::unique_ptrstats.inc (nano::stat::type::tcp_server, nano::to_stat_detail (message->header.type), nano::stat::dir::in); + node->stats.inc (nano::stat::type::tcp_server, to_stat_detail (message->header.type), nano::stat::dir::in); debug_assert (is_undefined_connection () || is_realtime_connection () || is_bootstrap_connection ()); @@ -448,6 +461,10 @@ bool nano::transport::tcp_server::process_message (std::unique_ptrlogger.debug (nano::log::type::tcp_server, "Neither handshake nor bootstrap received when in handshake mode: {} ({})", + nano::to_string (message->header.type), + nano::util::to_str (remote_endpoint)); + return true; } } @@ -500,10 +517,8 @@ void nano::transport::tcp_server::handshake_message_visitor::node_id_handshake ( } if (node->flags.disable_tcp_realtime) { - if (node->config.logging.network_node_id_handshake_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Disabled realtime TCP for handshake %1%") % server->remote_endpoint)); - } + node->logger.debug (nano::log::type::tcp_server, "Handshake attempted with disabled realtime TCP ({})", nano::util::to_str (server->remote_endpoint)); + // Stop invalid handshake server->stop (); return; @@ -511,10 +526,8 @@ void nano::transport::tcp_server::handshake_message_visitor::node_id_handshake ( if (message.query && server->handshake_query_received) { - if (node->config.logging.network_node_id_handshake_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Detected multiple node_id_handshake query from %1%") % server->remote_endpoint)); - } + node->logger.debug (nano::log::type::tcp_server, "Detected multiple handshake queries ({})", nano::util::to_str (server->remote_endpoint)); + // Stop invalid handshake server->stop (); return; @@ -522,10 +535,7 @@ void nano::transport::tcp_server::handshake_message_visitor::node_id_handshake ( server->handshake_query_received = true; - if (node->config.logging.network_node_id_handshake_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Received node_id_handshake message from %1%") % server->remote_endpoint)); - } + node->logger.debug (nano::log::type::tcp_server, "Handshake query received ({})", nano::util::to_str (server->remote_endpoint)); if (message.query) { @@ -569,10 +579,8 @@ void nano::transport::tcp_server::send_handshake_response (nano::node_id_handsha } if (ec) { - if (node->config.logging.network_node_id_handshake_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Error sending node_id_handshake to %1%: %2%") % this_l->remote_endpoint % ec.message ())); - } + node->logger.debug (nano::log::type::tcp_server, "Error sending handshake response: {} ({})", ec.message (), nano::util::to_str (this_l->remote_endpoint)); + // Stop invalid handshake this_l->stop (); } @@ -615,6 +623,7 @@ nano::transport::tcp_server::realtime_message_visitor::realtime_message_visitor void nano::transport::tcp_server::realtime_message_visitor::keepalive (const nano::keepalive & message) { process = true; + server.set_last_keepalive (message); } void nano::transport::tcp_server::realtime_message_visitor::publish (const nano::publish & message) @@ -692,11 +701,6 @@ void nano::transport::tcp_server::bootstrap_message_visitor::bulk_pull (const na return; } - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Received bulk pull for %1% down to %2%, maximum of %3% from %4%") % message.start.to_string () % message.end.to_string () % message.count % server->remote_endpoint)); - } - node->bootstrap_workers.push_task ([server = server, message = message] () { // TODO: Add completion callback to bulk pull server // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers @@ -719,11 +723,6 @@ void nano::transport::tcp_server::bootstrap_message_visitor::bulk_pull_account ( return; } - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Received bulk pull account for %1% with a minimum amount of %2%") % message.account.to_account () % nano::amount (message.minimum_amount).format_balance (nano::Mxrb_ratio, 10, true))); - } - node->bootstrap_workers.push_task ([server = server, message = message] () { // TODO: Add completion callback to bulk pull server // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers @@ -757,10 +756,6 @@ void nano::transport::tcp_server::bootstrap_message_visitor::frontier_req (const { return; } - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log (boost::str (boost::format ("Received frontier request for %1% with age %2%") % message.start.to_string () % message.age)); - } node->bootstrap_workers.push_task ([server = server, message = message] () { // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers @@ -782,10 +777,8 @@ void nano::transport::tcp_server::timeout () } if (socket->has_timed_out ()) { - if (node->config.logging.bulk_pull_logging ()) - { - node->logger.try_log ("Closing incoming tcp / bootstrap server by timeout"); - } + node->logger.debug (nano::log::type::tcp_server, "Closing TCP server due to timeout ({})", nano::util::to_str (remote_endpoint)); + { nano::lock_guard lock{ node->tcp_listener->mutex }; node->tcp_listener->connections.erase (this); @@ -794,6 +787,15 @@ void nano::transport::tcp_server::timeout () } } +void nano::transport::tcp_server::set_last_keepalive (nano::keepalive const & message) +{ + std::lock_guard lock{ mutex }; + if (!last_keepalive) + { + last_keepalive = message; + } +} + bool nano::transport::tcp_server::to_bootstrap_connection () { auto node = this->node.lock (); @@ -820,6 +822,9 @@ bool nano::transport::tcp_server::to_bootstrap_connection () ++node->tcp_listener->bootstrap_count; socket->type_set (nano::transport::socket::type_t::bootstrap); + + node->logger.debug (nano::log::type::tcp_server, "Switched to bootstrap mode ({})", nano::util::to_str (remote_endpoint)); + return true; } @@ -835,6 +840,9 @@ bool nano::transport::tcp_server::to_realtime_connection (nano::account const & remote_node_id = node_id; ++node->tcp_listener->realtime_count; socket->type_set (nano::transport::socket::type_t::realtime); + + node->logger.debug (nano::log::type::tcp_server, "Switched to realtime mode ({})", nano::util::to_str (remote_endpoint)); + return true; } return false; diff --git a/nano/node/transport/tcp_server.hpp b/nano/node/transport/tcp_server.hpp index e011c50630..5369258545 100644 --- a/nano/node/transport/tcp_server.hpp +++ b/nano/node/transport/tcp_server.hpp @@ -62,6 +62,7 @@ class tcp_server final : public std::enable_shared_from_this void stop (); void timeout (); + void set_last_keepalive (nano::keepalive const & message); std::shared_ptr const socket; std::weak_ptr const node; @@ -72,6 +73,7 @@ class tcp_server final : public std::enable_shared_from_this nano::tcp_endpoint remote_endpoint{ boost::asio::ip::address_v6::any (), 0 }; nano::account remote_node_id{}; std::chrono::steady_clock::time_point last_telemetry_req{}; + std::optional last_keepalive; private: void send_handshake_response (nano::node_id_handshake::query_payload const & query, bool v2); diff --git a/nano/node/unchecked_map.cpp b/nano/node/unchecked_map.cpp index 45d3b49563..4d65a40d2f 100644 --- a/nano/node/unchecked_map.cpp +++ b/nano/node/unchecked_map.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,7 +6,8 @@ #include #include -nano::unchecked_map::unchecked_map (nano::stats & stats, bool const & disable_delete) : +nano::unchecked_map::unchecked_map (unsigned const max_unchecked_blocks, nano::stats & stats, bool const & disable_delete) : + max_unchecked_blocks{ max_unchecked_blocks }, stats{ stats }, disable_delete{ disable_delete }, thread{ [this] () { run (); } } @@ -23,7 +25,8 @@ void nano::unchecked_map::put (nano::hash_or_account const & dependency, nano::u nano::lock_guard lock{ entries_mutex }; nano::unchecked_key key{ dependency, info.block->hash () }; entries.get ().insert ({ key, info }); - if (entries.size () > mem_block_count_max) + + if (entries.size () > max_unchecked_blocks) { entries.get ().pop_front (); } diff --git a/nano/node/unchecked_map.hpp b/nano/node/unchecked_map.hpp index b76e8ccb44..9a548c203d 100644 --- a/nano/node/unchecked_map.hpp +++ b/nano/node/unchecked_map.hpp @@ -22,7 +22,7 @@ class stats; class unchecked_map { public: - unchecked_map (nano::stats &, bool const & do_delete); + unchecked_map (unsigned const max_unchecked_blocks, nano::stats &, bool const & do_delete); ~unchecked_map (); void put (nano::hash_or_account const & dependency, nano::unchecked_info const & info); @@ -62,11 +62,10 @@ class unchecked_map nano::condition_variable condition; nano::mutex mutex; std::thread thread; + unsigned const max_unchecked_blocks; void process_queries (decltype (buffer) const & back_buffer); - static std::size_t constexpr mem_block_count_max = 64 * 1024; - private: struct entry { diff --git a/nano/node/vote_cache.cpp b/nano/node/vote_cache.cpp index 527ea0a097..78c6fa86ff 100644 --- a/nano/node/vote_cache.cpp +++ b/nano/node/vote_cache.cpp @@ -245,18 +245,9 @@ void nano::vote_cache::cleanup () auto const cutoff = std::chrono::steady_clock::now () - config.age_cutoff; - auto it = cache.begin (); - while (it != cache.end ()) - { - if (it->last_vote () < cutoff) - { - it = cache.erase (it); - } - else - { - ++it; - } - } + erase_if (cache, [cutoff] (auto const & entry) { + return entry.last_vote () < cutoff; + }); } std::unique_ptr nano::vote_cache::collect_container_info (const std::string & name) const diff --git a/nano/node/vote_processor.cpp b/nano/node/vote_processor.cpp index 76a32d59df..337b0bddfb 100644 --- a/nano/node/vote_processor.cpp +++ b/nano/node/vote_processor.cpp @@ -1,10 +1,10 @@ -#include #include #include #include #include #include #include +#include #include #include #include @@ -13,45 +13,59 @@ #include #include + using namespace std::chrono_literals; -nano::vote_processor::vote_processor (nano::active_transactions & active_a, nano::node_observers & observers_a, nano::stats & stats_a, nano::node_config & config_a, nano::node_flags & flags_a, nano::logger_mt & logger_a, nano::online_reps & online_reps_a, nano::rep_crawler & rep_crawler_a, nano::ledger & ledger_a, nano::network_params & network_params_a) : - active (active_a), - observers (observers_a), - stats (stats_a), - config (config_a), - logger (logger_a), - online_reps (online_reps_a), - rep_crawler (rep_crawler_a), - ledger (ledger_a), - network_params (network_params_a), - max_votes (flags_a.vote_processor_capacity), - started (false), - stopped (false), - thread ([this] () { +nano::vote_processor::vote_processor (nano::active_transactions & active_a, nano::node_observers & observers_a, nano::stats & stats_a, nano::node_config & config_a, nano::node_flags & flags_a, nano::logger & logger_a, nano::online_reps & online_reps_a, nano::rep_crawler & rep_crawler_a, nano::ledger & ledger_a, nano::network_params & network_params_a, nano::rep_tiers & rep_tiers_a) : + active{ active_a }, + observers{ observers_a }, + stats{ stats_a }, + config{ config_a }, + logger{ logger_a }, + online_reps{ online_reps_a }, + rep_crawler{ rep_crawler_a }, + ledger{ ledger_a }, + network_params{ network_params_a }, + rep_tiers{ rep_tiers_a }, + max_votes{ flags_a.vote_processor_capacity } +{ +} + +nano::vote_processor::~vote_processor () +{ + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); +} + +void nano::vote_processor::start () +{ + debug_assert (!thread.joinable ()); + + thread = std::thread{ [this] () { nano::thread_role::set (nano::thread_role::name::vote_processing); - process_loop (); - nano::unique_lock lock{ mutex }; - votes.clear (); - condition.notify_all (); - }) + run (); + } }; +} + +void nano::vote_processor::stop () { - nano::unique_lock lock{ mutex }; - condition.wait (lock, [&started = started] { return started; }); + { + nano::lock_guard lock{ mutex }; + stopped = true; + } + condition.notify_all (); + if (thread.joinable ()) + { + thread.join (); + } } -void nano::vote_processor::process_loop () +void nano::vote_processor::run () { nano::timer elapsed; bool log_this_iteration; nano::unique_lock lock{ mutex }; - started = true; - - lock.unlock (); - condition.notify_all (); - lock.lock (); - while (!stopped) { if (!votes.empty ()) @@ -62,7 +76,8 @@ void nano::vote_processor::process_loop () condition.notify_all (); log_this_iteration = false; - if (config.logging.network_logging () && votes_l.size () > 50) + // TODO: This is a temporary measure to prevent spamming the logs until we can implement a better solution + if (votes_l.size () > 1024 * 4) { /* * Only log the timing information for this iteration if @@ -76,8 +91,12 @@ void nano::vote_processor::process_loop () if (log_this_iteration && elapsed.stop () > std::chrono::milliseconds (100)) { - logger.try_log (boost::str (boost::format ("Processed %1% votes in %2% milliseconds (rate of %3% votes per second)") % votes_l.size () % elapsed.value ().count () % ((votes_l.size () * 1000ULL) / elapsed.value ().count ()))); + logger.debug (nano::log::type::vote_processor, "Processed {} votes in {} milliseconds (rate of {} votes per second)", + votes_l.size (), + elapsed.value ().count (), + ((votes_l.size () * 1000ULL) / elapsed.value ().count ())); } + lock.lock (); } else @@ -94,6 +113,8 @@ bool nano::vote_processor::vote (std::shared_ptr const & vote_a, std nano::unique_lock lock{ mutex }; if (!stopped) { + auto tier = rep_tiers.tier (vote_a->account); + // Level 0 (< 0.1%) if (votes.size () < 6.0 / 9.0 * max_votes) { @@ -102,17 +123,17 @@ bool nano::vote_processor::vote (std::shared_ptr const & vote_a, std // Level 1 (0.1-1%) else if (votes.size () < 7.0 / 9.0 * max_votes) { - process = (representatives_1.find (vote_a->account) != representatives_1.end ()); + process = (tier == nano::rep_tier::tier_1); } // Level 2 (1-5%) else if (votes.size () < 8.0 / 9.0 * max_votes) { - process = (representatives_2.find (vote_a->account) != representatives_2.end ()); + process = (tier == nano::rep_tier::tier_2); } // Level 3 (> 5%) else if (votes.size () < max_votes) { - process = (representatives_3.find (vote_a->account) != representatives_3.end ()); + process = (tier == nano::rep_tier::tier_3); } if (process) { @@ -168,24 +189,12 @@ nano::vote_code nano::vote_processor::vote_blocking (std::shared_ptr stats.inc (nano::stat::type::vote, nano::stat::detail::vote_indeterminate); break; } - if (config.logging.vote_logging ()) - { - logger.try_log (boost::str (boost::format ("Vote from: %1% timestamp: %2% duration %3%ms block(s): %4% status: %5%") % vote_a->account.to_account () % std::to_string (vote_a->timestamp ()) % std::to_string (vote_a->duration ().count ()) % vote_a->hashes_string () % status)); - } - return result; -} -void nano::vote_processor::stop () -{ - { - nano::lock_guard lock{ mutex }; - stopped = true; - } - condition.notify_all (); - if (thread.joinable ()) - { - thread.join (); - } + logger.trace (nano::log::type::vote_processor, nano::log::detail::vote_processed, + nano::log::arg{ "vote", vote_a }, + nano::log::arg{ "result", result }); + + return result; } void nano::vote_processor::flush () @@ -197,77 +206,31 @@ void nano::vote_processor::flush () }); if (!success) { - logger.always_log ("WARNING: vote_processor::flush timeout while waiting for flush"); + logger.error (nano::log::type::vote_processor, "Flush timeout"); debug_assert (false && "vote_processor::flush timeout while waiting for flush"); } } -std::size_t nano::vote_processor::size () +std::size_t nano::vote_processor::size () const { nano::lock_guard guard{ mutex }; return votes.size (); } -bool nano::vote_processor::empty () +bool nano::vote_processor::empty () const { nano::lock_guard guard{ mutex }; return votes.empty (); } -bool nano::vote_processor::half_full () -{ - return size () >= max_votes / 2; -} - -void nano::vote_processor::calculate_weights () -{ - nano::unique_lock lock{ mutex }; - if (!stopped) - { - representatives_1.clear (); - representatives_2.clear (); - representatives_3.clear (); - auto supply (online_reps.trended ()); - auto rep_amounts = ledger.cache.rep_weights.get_rep_amounts (); - for (auto const & rep_amount : rep_amounts) - { - nano::account const & representative (rep_amount.first); - auto weight (ledger.weight (representative)); - if (weight > supply / 1000) // 0.1% or above (level 1) - { - representatives_1.insert (representative); - if (weight > supply / 100) // 1% or above (level 2) - { - representatives_2.insert (representative); - if (weight > supply / 20) // 5% or above (level 3) - { - representatives_3.insert (representative); - } - } - } - } - } -} - std::unique_ptr nano::collect_container_info (vote_processor & vote_processor, std::string const & name) { std::size_t votes_count; - std::size_t representatives_1_count; - std::size_t representatives_2_count; - std::size_t representatives_3_count; - { nano::lock_guard guard{ vote_processor.mutex }; votes_count = vote_processor.votes.size (); - representatives_1_count = vote_processor.representatives_1.size (); - representatives_2_count = vote_processor.representatives_2.size (); - representatives_3_count = vote_processor.representatives_3.size (); } - auto composite = std::make_unique (name); composite->add_component (std::make_unique (container_info{ "votes", votes_count, sizeof (decltype (vote_processor.votes)::value_type) })); - composite->add_component (std::make_unique (container_info{ "representatives_1", representatives_1_count, sizeof (decltype (vote_processor.representatives_1)::value_type) })); - composite->add_component (std::make_unique (container_info{ "representatives_2", representatives_2_count, sizeof (decltype (vote_processor.representatives_2)::value_type) })); - composite->add_component (std::make_unique (container_info{ "representatives_3", representatives_3_count, sizeof (decltype (vote_processor.representatives_3)::value_type) })); return composite; } diff --git a/nano/node/vote_processor.hpp b/nano/node/vote_processor.hpp index 4ee3c6f0ea..b7498180fc 100644 --- a/nano/node/vote_processor.hpp +++ b/nano/node/vote_processor.hpp @@ -11,7 +11,6 @@ namespace nano { -class signature_checker; class active_transactions; namespace store { @@ -20,13 +19,14 @@ namespace store class node_observers; class stats; class node_config; -class logger_mt; +class logger; class online_reps; class rep_crawler; class ledger; class network_params; class node_flags; class stats; +class rep_tiers; namespace transport { @@ -36,49 +36,52 @@ namespace transport class vote_processor final { public: - vote_processor (nano::active_transactions & active_a, nano::node_observers & observers_a, nano::stats & stats_a, nano::node_config & config_a, nano::node_flags & flags_a, nano::logger_mt & logger_a, nano::online_reps & online_reps_a, nano::rep_crawler & rep_crawler_a, nano::ledger & ledger_a, nano::network_params & network_params_a); + vote_processor (nano::active_transactions &, nano::node_observers &, nano::stats &, nano::node_config &, nano::node_flags &, nano::logger &, nano::online_reps &, nano::rep_crawler &, nano::ledger &, nano::network_params &, nano::rep_tiers &); + ~vote_processor (); + + void start (); + void stop (); /** Returns false if the vote was processed */ bool vote (std::shared_ptr const &, std::shared_ptr const &); /** Note: node.active.mutex lock is required */ nano::vote_code vote_blocking (std::shared_ptr const &, std::shared_ptr const &, bool = false); - void verify_votes (std::deque, std::shared_ptr>> const &); + /** Function blocks until either the current queue size (a established flush boundary as it'll continue to increase) * is processed or the queue is empty (end condition or cutoff's guard, as it is positioned ahead) */ void flush (); - std::size_t size (); - bool empty (); - bool half_full (); - void calculate_weights (); - void stop (); - std::atomic total_processed{ 0 }; + std::size_t size () const; + bool empty () const; -private: - void process_loop (); + std::atomic total_processed{ 0 }; +private: // Dependencies nano::active_transactions & active; nano::node_observers & observers; nano::stats & stats; nano::node_config & config; - nano::logger_mt & logger; + nano::logger & logger; nano::online_reps & online_reps; nano::rep_crawler & rep_crawler; nano::ledger & ledger; nano::network_params & network_params; + nano::rep_tiers & rep_tiers; + +private: + void run (); + void verify_votes (std::deque, std::shared_ptr>> const &); + +private: std::size_t const max_votes; std::deque, std::shared_ptr>> votes; - /** Representatives levels for random early detection */ - std::unordered_set representatives_1; - std::unordered_set representatives_2; - std::unordered_set representatives_3; + +private: + bool stopped{ false }; nano::condition_variable condition; - nano::mutex mutex{ mutex_identifier (mutexes::vote_processor) }; - bool started; - bool stopped; + mutable nano::mutex mutex{ mutex_identifier (mutexes::vote_processor) }; std::thread thread; friend std::unique_ptr collect_container_info (vote_processor & vote_processor, std::string const & name); - friend class vote_processor_weights_Test; }; std::unique_ptr collect_container_info (vote_processor & vote_processor, std::string const & name); diff --git a/nano/node/voting.cpp b/nano/node/voting.cpp index 401ebe8327..9967f7edb5 100644 --- a/nano/node/voting.cpp +++ b/nano/node/voting.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -161,7 +162,7 @@ std::unique_ptr nano::collect_container_info (na return composite; } -nano::vote_generator::vote_generator (nano::node_config const & config_a, nano::ledger & ledger_a, nano::wallets & wallets_a, nano::vote_processor & vote_processor_a, nano::local_vote_history & history_a, nano::network & network_a, nano::stats & stats_a, bool is_final_a) : +nano::vote_generator::vote_generator (nano::node_config const & config_a, nano::ledger & ledger_a, nano::wallets & wallets_a, nano::vote_processor & vote_processor_a, nano::local_vote_history & history_a, nano::network & network_a, nano::stats & stats_a, nano::logger & logger_a, bool is_final_a) : config (config_a), ledger (ledger_a), wallets (wallets_a), @@ -170,6 +171,7 @@ nano::vote_generator::vote_generator (nano::node_config const & config_a, nano:: spacing{ config_a.network_params.voting.delay }, network (network_a), stats (stats_a), + logger (logger_a), is_final (is_final_a), vote_generation_queue{ stats, nano::stat::type::vote_generator, nano::thread_role::name::vote_generator_queue, /* single threaded */ 1, /* max queue size */ 1024 * 32, /* max batch size */ 1024 * 4 } { @@ -185,18 +187,23 @@ nano::vote_generator::~vote_generator () bool nano::vote_generator::should_vote (store::write_transaction const & transaction, nano::root const & root_a, nano::block_hash const & hash_a) { + auto block = ledger.block (transaction, hash_a); bool should_vote = false; if (is_final) { - auto block (ledger.store.block.get (transaction, hash_a)); should_vote = block != nullptr && ledger.dependents_confirmed (transaction, *block) && ledger.store.final_vote.put (transaction, block->qualified_root (), hash_a); debug_assert (block == nullptr || root_a == block->root ()); } else { - auto block (ledger.store.block.get (transaction, hash_a)); should_vote = block != nullptr && ledger.dependents_confirmed (transaction, *block); } + + logger.trace (nano::log::type::vote_generator, nano::log::detail::should_vote, + nano::log::arg{ "should_vote", should_vote }, + nano::log::arg{ "block", block }, + nano::log::arg{ "is_final", is_final }); + return should_vote; } diff --git a/nano/node/voting.hpp b/nano/node/voting.hpp index def5f78a56..6a2b2c79b6 100644 --- a/nano/node/voting.hpp +++ b/nano/node/voting.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -121,7 +122,7 @@ class vote_generator final using queue_entry_t = std::pair; public: - vote_generator (nano::node_config const & config_a, nano::ledger & ledger_a, nano::wallets & wallets_a, nano::vote_processor & vote_processor_a, nano::local_vote_history & history_a, nano::network & network_a, nano::stats & stats_a, bool is_final_a); + vote_generator (nano::node_config const &, nano::ledger &, nano::wallets &, nano::vote_processor &, nano::local_vote_history &, nano::network &, nano::stats &, nano::logger &, bool is_final); ~vote_generator (); /** Queue items for vote generation, or broadcast votes already in cache */ @@ -159,6 +160,7 @@ class vote_generator final nano::vote_spacing spacing; nano::network & network; nano::stats & stats; + nano::logger & logger; private: processing_queue vote_generation_queue; diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index c98beb182c..6d7b6cd7a6 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -1,9 +1,11 @@ #include +#include #include #include #include #include #include +#include #include #include @@ -699,16 +701,17 @@ bool nano::wallet::enter_password (store::transaction const & transaction_a, std auto result (store.attempt_password (transaction_a, password_a)); if (!result) { + wallets.node.logger.info (nano::log::type::wallet, "Wallet unlocked"); + auto this_l = shared_from_this (); wallets.queue_wallet_action (nano::wallets::high_priority, this_l, [this_l] (nano::wallet & wallet) { // Wallets must survive node lifetime this_l->search_receivable (this_l->wallets.tx_begin_read ()); }); - wallets.node.logger.try_log ("Wallet unlocked"); } else { - wallets.node.logger.try_log ("Invalid password, wallet locked"); + wallets.node.logger.warn (nano::log::type::wallet, "Invalid password, wallet locked"); } lock_observer (result, password_a.empty ()); return result; @@ -865,7 +868,7 @@ std::shared_ptr nano::wallet::receive_action (nano::block_hash cons } else { - wallets.node.logger.try_log ("Unable to receive, wallet locked"); + wallets.node.logger.warn (nano::log::type::wallet, "Unable to receive, wallet locked"); } } else @@ -880,8 +883,8 @@ std::shared_ptr nano::wallet::receive_action (nano::block_hash cons } else { - wallets.node.logger.try_log (boost::str (boost::format ("Not receiving block %1% due to minimum receive threshold") % send_hash_a.to_string ())); // Someone sent us something below the threshold of receiving + wallets.node.logger.warn (nano::log::type::wallet, "Not receiving block {} due to minimum receive threshold", send_hash_a.to_string ()); } if (block != nullptr) { @@ -954,7 +957,7 @@ std::shared_ptr nano::wallet::send_action (nano::account const & so if (status == 0) { nano::block_hash hash (result); - block = wallets.node.store.block.get (block_transaction, hash); + block = wallets.node.ledger.block (block_transaction, hash); if (block != nullptr) { cached_block = true; @@ -1043,14 +1046,17 @@ bool nano::wallet::action_complete (std::shared_ptr const & block_a auto required_difficulty{ wallets.node.network_params.work.threshold (block_a->work_version (), details_a) }; if (wallets.node.network_params.work.difficulty (*block_a) < required_difficulty) { - wallets.node.logger.try_log (boost::str (boost::format ("Cached or provided work for block %1% account %2% is invalid, regenerating") % block_a->hash ().to_string () % account_a.to_account ())); + wallets.node.logger.info (nano::log::type::wallet, "Cached or provided work for block {} account {} is invalid, regenerating...", + block_a->hash ().to_string (), + account_a.to_account ()); + debug_assert (required_difficulty <= wallets.node.max_work_generate_difficulty (block_a->work_version ())); - error = !wallets.node.work_generate_blocking (*block_a, required_difficulty).is_initialized (); + error = !wallets.node.work_generate_blocking (*block_a, required_difficulty).has_value (); } if (!error) { auto result = wallets.node.process_local (block_a); - error = !result || result.value ().code != nano::process_result::progress; + error = !result || result.value () != nano::block_status::progress; debug_assert (error || block_a->sideband ().details == details_a); } if (!error && generate_work_a) @@ -1087,9 +1093,8 @@ bool nano::wallet::receive_sync (std::shared_ptr const & block_a, n { std::promise result; std::future future = result.get_future (); - auto destination (block_a->link ().is_zero () ? block_a->destination () : block_a->link ().as_account ()); receive_async ( - block_a->hash (), representative_a, amount_a, destination, [&result] (std::shared_ptr const & block_a) { + block_a->hash (), representative_a, amount_a, block_a->destination (), [&result] (std::shared_ptr const & block_a) { result.set_value (block_a == nullptr); }, true); @@ -1139,7 +1144,7 @@ void nano::wallet::work_update (store::transaction const & transaction_a, nano:: } else { - wallets.node.logger.try_log ("Cached work no longer valid, discarding"); + wallets.node.logger.warn (nano::log::type::wallet, "Cached work no longer valid, discarding"); } } @@ -1168,7 +1173,8 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact auto result (!store.valid_password (wallet_transaction_a)); if (!result) { - wallets.node.logger.try_log ("Beginning receivable block search"); + wallets.node.logger.info (nano::log::type::wallet, "Beginning receivable block search"); + for (auto i (store.begin (wallet_transaction_a)), n (store.end ()); i != n; ++i) { auto block_transaction (wallets.node.store.tx_begin_read ()); @@ -1184,7 +1190,8 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact auto amount (pending.amount.number ()); if (wallets.node.config.receive_minimum.number () <= amount) { - wallets.node.logger.try_log (boost::str (boost::format ("Found a receivable block %1% for account %2%") % hash.to_string () % pending.source.to_account ())); + wallets.node.logger.info (nano::log::type::wallet, "Found a receivable block {} for account {}", hash.to_string (), pending.source.to_account ()); + if (wallets.node.ledger.block_confirmed (block_transaction, hash)) { auto representative = store.representative (wallet_transaction_a); @@ -1193,7 +1200,7 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact } else if (!wallets.node.confirmation_height_processor.is_processing_block (hash)) { - auto block (wallets.node.store.block.get (block_transaction, hash)); + auto block = wallets.node.ledger.block (block_transaction, hash); if (block) { // Request confirmation for block which is not being processed yet @@ -1204,11 +1211,12 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact } } } - wallets.node.logger.try_log ("Receivable block search phase completed"); + + wallets.node.logger.info (nano::log::type::wallet, "Receivable block search phase complete"); } else { - wallets.node.logger.try_log ("Stopping search, wallet is locked"); + wallets.node.logger.warn (nano::log::type::wallet, "Stopping search, wallet is locked"); } return result; } @@ -1290,17 +1298,17 @@ void nano::wallet::work_cache_blocking (nano::account const & account_a, nano::r { auto difficulty (wallets.node.default_difficulty (nano::work_version::work_1)); auto opt_work_l (wallets.node.work_generate_blocking (nano::work_version::work_1, root_a, difficulty, account_a)); - if (opt_work_l.is_initialized ()) + if (opt_work_l.has_value ()) { auto transaction_l (wallets.tx_begin_write ()); if (live () && store.exists (transaction_l, account_a)) { - work_update (transaction_l, account_a, root_a, *opt_work_l); + work_update (transaction_l, account_a, root_a, opt_work_l.value ()); } } else if (!wallets.node.stopped) { - wallets.node.logger.try_log (boost::str (boost::format ("Could not precache work for root %1% due to work generation failure") % root_a.to_string ())); + wallets.node.logger.warn (nano::log::type::wallet, "Could not precache work for root {} due to work generation failure", root_a.to_string ()); } } } @@ -1556,11 +1564,13 @@ void nano::wallets::foreach_representative (std::functionfirst.to_string ())); + + node.logger.warn (nano::log::type::wallet, "Representative locked inside wallet: {}", i->first.to_string ()); } } } diff --git a/nano/node/websocket.cpp b/nano/node/websocket.cpp index fd436c6b14..68f870a3c0 100644 --- a/nano/node/websocket.cpp +++ b/nano/node/websocket.cpp @@ -1,12 +1,15 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include @@ -14,12 +17,13 @@ #include #include -nano::websocket::confirmation_options::confirmation_options (nano::wallets & wallets_a) : - wallets (wallets_a) +nano::websocket::confirmation_options::confirmation_options (nano::wallets & wallets_a, nano::logger & logger_a) : + wallets (wallets_a), + logger (logger_a) { } -nano::websocket::confirmation_options::confirmation_options (boost::property_tree::ptree const & options_a, nano::wallets & wallets_a, nano::logger_mt & logger_a) : +nano::websocket::confirmation_options::confirmation_options (boost::property_tree::ptree const & options_a, nano::wallets & wallets_a, nano::logger & logger_a) : wallets (wallets_a), logger (logger_a) { @@ -62,7 +66,7 @@ nano::websocket::confirmation_options::confirmation_options (boost::property_tre if (!include_block) { - logger_a.always_log ("Websocket: Filtering option \"all_local_accounts\" requires that \"include_block\" is set to true to be effective"); + logger.warn (nano::log::type::websocket, "Filtering option \"all_local_accounts\" requires that \"include_block\" is set to true to be effective"); } } auto accounts_l (options_a.get_child_optional ("accounts")); @@ -79,13 +83,13 @@ nano::websocket::confirmation_options::confirmation_options (boost::property_tre } else { - logger_a.always_log ("Websocket: invalid account provided for filtering blocks: ", account_l.second.data ()); + logger.warn (nano::log::type::websocket, "Invalid account provided for filtering blocks: ", account_l.second.data ()); } } if (!include_block) { - logger_a.always_log ("Websocket: Filtering option \"accounts\" requires that \"include_block\" is set to true to be effective"); + logger.warn (nano::log::type::websocket, "Filtering option \"accounts\" requires that \"include_block\" is set to true to be effective"); } } check_filter_empty (); @@ -158,9 +162,9 @@ bool nano::websocket::confirmation_options::update (boost::property_tree::ptree this->accounts.erase (encoded_l); } } - else if (this->logger.is_initialized ()) + else { - this->logger->always_log ("Websocket: invalid account provided for filtering blocks: ", account_l.second.data ()); + logger.warn (nano::log::type::websocket, "Invalid account provided for filtering blocks: ", account_l.second.data ()); } } }; @@ -186,13 +190,13 @@ bool nano::websocket::confirmation_options::update (boost::property_tree::ptree void nano::websocket::confirmation_options::check_filter_empty () const { // Warn the user if the options resulted in an empty filter - if (logger.is_initialized () && has_account_filtering_options && !all_local_accounts && accounts.empty ()) + if (has_account_filtering_options && !all_local_accounts && accounts.empty ()) { - logger->always_log ("Websocket: provided options resulted in an empty block confirmation filter"); + logger.warn (nano::log::type::websocket, "Provided options resulted in an empty account confirmation filter"); } } -nano::websocket::vote_options::vote_options (boost::property_tree::ptree const & options_a, nano::logger_mt & logger_a) +nano::websocket::vote_options::vote_options (boost::property_tree::ptree const & options_a, nano::logger & logger) { include_replays = options_a.get ("include_replays", false); include_indeterminate = options_a.get ("include_indeterminate", false); @@ -209,13 +213,13 @@ nano::websocket::vote_options::vote_options (boost::property_tree::ptree const & } else { - logger_a.always_log ("Websocket: invalid account given to filter votes: ", representative_l.second.data ()); + logger.warn (nano::log::type::websocket, "Invalid account provided for filtering votes: ", representative_l.second.data ()); } } // Warn the user if the option will be ignored if (representatives.empty ()) { - logger_a.always_log ("Websocket: account filter for votes is empty, no messages will be filtered"); + logger.warn (nano::log::type::websocket, "Account filter for votes is empty, no messages will be filtered"); } } } @@ -240,15 +244,25 @@ bool nano::websocket::vote_options::should_filter (nano::websocket::message cons nano::websocket::session::session (nano::websocket::listener & listener_a, socket_type socket_a, boost::asio::ssl::context & ctx_a) : ws_listener (listener_a), ws (std::move (socket_a), ctx_a) { - ws_listener.get_logger ().try_log ("Websocket: secure session started"); } #endif -nano::websocket::session::session (nano::websocket::listener & listener_a, socket_type socket_a) : - ws_listener (listener_a), ws (std::move (socket_a)) +nano::websocket::session::session (nano::websocket::listener & listener_a, socket_type socket_a, nano::logger & logger_a) : + ws_listener (listener_a), + ws (std::move (socket_a)), + logger (logger_a) { - ws_listener.get_logger ().try_log ("Websocket: session started"); + { + // Best effort attempt to get endpoint addresses + boost::system::error_code ec; + remote = ws.get_socket ().remote_endpoint (ec); + debug_assert (!ec); + local = ws.get_socket ().local_endpoint (ec); + debug_assert (!ec); + } + + logger.info (nano::log::type::websocket, "Session started ({})", nano::util::to_str (remote)); } nano::websocket::session::~session () @@ -273,14 +287,14 @@ void nano::websocket::session::handshake () } else { - this_l->ws_listener.get_logger ().always_log ("Websocket: handshake failed: ", ec.message ()); + this_l->logger.error (nano::log::type::websocket, "Handshake failed: {} ({})", ec.message (), nano::util::to_str (this_l->remote)); } }); } void nano::websocket::session::close () { - ws_listener.get_logger ().try_log ("Websocket: session closing"); + logger.info (nano::log::type::websocket, "Session closing ({})", nano::util::to_str (remote)); auto this_l (shared_from_this ()); boost::asio::dispatch (ws.get_strand (), @@ -356,12 +370,12 @@ void nano::websocket::session::read () } catch (boost::property_tree::json_parser::json_parser_error const & ex) { - this_l->ws_listener.get_logger ().try_log ("Websocket: json parsing failed: ", ex.what ()); + this_l->logger.error (nano::log::type::websocket, "JSON parsing failed: {} ({})", ex.what (), nano::util::to_str (this_l->remote)); } } else if (ec != boost::asio::error::eof) { - this_l->ws_listener.get_logger ().try_log ("Websocket: read failed: ", ec.message ()); + this_l->logger.error (nano::log::type::websocket, "Read failed: {} ({})", ec.message (), nano::util::to_str (this_l->remote)); } }); }); @@ -483,11 +497,11 @@ void nano::websocket::session::handle_message (boost::property_tree::ptree const std::unique_ptr options_l{ nullptr }; if (options_text_l && topic_l == nano::websocket::topic::confirmation) { - options_l = std::make_unique (options_text_l.get (), ws_listener.get_wallets (), ws_listener.get_logger ()); + options_l = std::make_unique (options_text_l.get (), ws_listener.get_wallets (), logger); } else if (options_text_l && topic_l == nano::websocket::topic::vote) { - options_l = std::make_unique (options_text_l.get (), ws_listener.get_logger ()); + options_l = std::make_unique (options_text_l.get (), logger); } else { @@ -496,13 +510,15 @@ void nano::websocket::session::handle_message (boost::property_tree::ptree const auto existing (subscriptions.find (topic_l)); if (existing != subscriptions.end ()) { + logger.info (nano::log::type::websocket, "Updated subscription to topic: {} ({})", from_topic (topic_l), nano::util::to_str (remote)); + existing->second = std::move (options_l); - ws_listener.get_logger ().always_log ("Websocket: updated subscription to topic: ", from_topic (topic_l)); } else { + logger.info (nano::log::type::websocket, "New subscription to topic: {} ({})", from_topic (topic_l), nano::util::to_str (remote)); + subscriptions.emplace (topic_l, std::move (options_l)); - ws_listener.get_logger ().always_log ("Websocket: new subscription to topic: ", from_topic (topic_l)); ws_listener.increase_subscriber_count (topic_l); } action_succeeded = true; @@ -525,7 +541,8 @@ void nano::websocket::session::handle_message (boost::property_tree::ptree const nano::lock_guard lk (subscriptions_mutex); if (subscriptions.erase (topic_l)) { - ws_listener.get_logger ().always_log ("Websocket: removed subscription to topic: ", from_topic (topic_l)); + logger.info (nano::log::type::websocket, "Removed subscription to topic: {} ({})", from_topic (topic_l), nano::util::to_str (remote)); + ws_listener.decrease_subscriber_count (topic_l); } action_succeeded = true; @@ -559,7 +576,7 @@ void nano::websocket::listener::stop () sessions.clear (); } -nano::websocket::listener::listener (std::shared_ptr const & tls_config_a, nano::logger_mt & logger_a, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a) : +nano::websocket::listener::listener (std::shared_ptr const & tls_config_a, nano::logger & logger_a, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a) : tls_config (tls_config_a), logger (logger_a), wallets (wallets_a), @@ -579,7 +596,7 @@ nano::websocket::listener::listener (std::shared_ptr const & t } catch (std::exception const & ex) { - logger.always_log ("Websocket: listen failed: ", ex.what ()); + logger.error (nano::log::type::websocket, "Listen failed: {}", ex.what ()); } } @@ -604,7 +621,7 @@ void nano::websocket::listener::on_accept (boost::system::error_code ec) { if (ec) { - logger.always_log ("Websocket: accept failed: ", ec.message ()); + logger.error (nano::log::type::websocket, "Accept failed: {}", ec.message ()); } else { @@ -618,7 +635,7 @@ void nano::websocket::listener::on_accept (boost::system::error_code ec) } else { - session = std::make_shared (*this, std::move (socket)); + session = std::make_shared (*this, std::move (socket), logger); } sessions_mutex.lock (); @@ -650,7 +667,7 @@ void nano::websocket::listener::broadcast_confirmation (std::shared_ptrsubscriptions.find (nano::websocket::topic::confirmation)); if (subscription != session_ptr->subscriptions.end ()) { - nano::websocket::confirmation_options default_options (wallets); + nano::websocket::confirmation_options default_options (wallets, logger); auto conf_options (dynamic_cast (subscription->second.get ())); if (conf_options == nullptr) { @@ -967,7 +984,7 @@ std::string nano::websocket::message::to_string () const * websocket_server */ -nano::websocket_server::websocket_server (nano::websocket::config & config_a, nano::node_observers & observers_a, nano::wallets & wallets_a, nano::ledger & ledger_a, boost::asio::io_context & io_ctx_a, nano::logger_mt & logger_a) : +nano::websocket_server::websocket_server (nano::websocket::config & config_a, nano::node_observers & observers_a, nano::wallets & wallets_a, nano::ledger & ledger_a, boost::asio::io_context & io_ctx_a, nano::logger & logger_a) : config{ config_a }, observers{ observers_a }, wallets{ wallets_a }, @@ -996,13 +1013,13 @@ nano::websocket_server::websocket_server (nano::websocket::config & config_a, na } else if (block_a->type () == nano::block_type::state) { - if (block_a->link ().is_zero ()) + if (block_a->is_change ()) { subtype = "change"; } else if (is_state_epoch_a) { - debug_assert (amount_a == 0 && ledger.is_epoch_link (block_a->link ())); + debug_assert (amount_a == 0 && ledger.is_epoch_link (block_a->link_field ().value ())); subtype = "epoch"; } else @@ -1063,4 +1080,4 @@ void nano::websocket_server::stop () { server->stop (); } -} \ No newline at end of file +} diff --git a/nano/node/websocket.hpp b/nano/node/websocket.hpp index 9d197dcfb6..6212198400 100644 --- a/nano/node/websocket.hpp +++ b/nano/node/websocket.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -20,15 +19,20 @@ namespace nano { -class wallets; -class logger_mt; -class vote; +class block; class election_status; +enum class election_status_type : uint8_t; +class ledger; +class logger; +class node_observers; class telemetry_data; class tls_config; -class node_observers; -enum class election_status_type : uint8_t; +class vote; +class wallets; +} +namespace nano +{ namespace websocket { class listener; @@ -142,8 +146,8 @@ namespace websocket class confirmation_options final : public options { public: - confirmation_options (nano::wallets & wallets_a); - confirmation_options (boost::property_tree::ptree const & options_a, nano::wallets & wallets_a, nano::logger_mt & logger_a); + confirmation_options (nano::wallets & wallets_a, nano::logger &); + confirmation_options (boost::property_tree::ptree const & options_a, nano::wallets & wallets_a, nano::logger &); /** * Checks if a message should be filtered for given block confirmation options. @@ -195,7 +199,8 @@ namespace websocket void check_filter_empty () const; nano::wallets & wallets; - boost::optional logger; + nano::logger & logger; + bool include_election_info{ false }; bool include_election_info_with_votes{ false }; bool include_sideband_info{ false }; @@ -214,7 +219,7 @@ namespace websocket class vote_options final : public options { public: - vote_options (boost::property_tree::ptree const & options_a, nano::logger_mt & logger_a); + vote_options (boost::property_tree::ptree const & options_a, nano::logger &); /** * Checks if a message should be filtered for given vote received options. @@ -240,7 +245,7 @@ namespace websocket explicit session (nano::websocket::listener & listener_a, socket_type socket_a, boost::asio::ssl::context & ctx_a); #endif /** Constructor that takes ownership over \p socket_a */ - explicit session (nano::websocket::listener & listener_a, socket_type socket_a); + explicit session (nano::websocket::listener & listener_a, socket_type socket_a, nano::logger &); ~session (); @@ -261,11 +266,17 @@ namespace websocket nano::websocket::listener & ws_listener; /** Websocket stream, supporting both plain and tls connections */ nano::websocket::stream ws; + nano::logger & logger; + /** Buffer for received messages */ boost::beast::multi_buffer read_buffer; /** Outgoing messages. The send queue is protected by accessing it only through the strand */ std::deque send_queue; + /** Cache remote & local endpoints to make them available after the socket is closed */ + socket_type::endpoint_type remote; + socket_type::endpoint_type local; + /** Hash functor for topic enums */ struct topic_hash { @@ -291,7 +302,7 @@ namespace websocket class listener final : public std::enable_shared_from_this { public: - listener (std::shared_ptr const & tls_config_a, nano::logger_mt & logger_a, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a); + listener (std::shared_ptr const & tls_config_a, nano::logger &, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a); /** Start accepting connections */ void run (); @@ -307,11 +318,6 @@ namespace websocket /** Broadcast \p message to all session subscribing to the message topic. */ void broadcast (nano::websocket::message message_a); - nano::logger_mt & get_logger () const - { - return logger; - } - std::uint16_t listening_port () { return acceptor.local_endpoint ().port (); @@ -346,7 +352,7 @@ namespace websocket void decrease_subscriber_count (nano::websocket::topic const & topic_a); std::shared_ptr tls_config; - nano::logger_mt & logger; + nano::logger & logger; nano::wallets & wallets; boost::asio::ip::tcp::acceptor acceptor; socket_type socket; @@ -363,7 +369,7 @@ namespace websocket class websocket_server { public: - websocket_server (nano::websocket::config &, nano::node_observers &, nano::wallets &, nano::ledger &, boost::asio::io_context &, nano::logger_mt &); + websocket_server (nano::websocket::config &, nano::node_observers &, nano::wallets &, nano::ledger &, boost::asio::io_context &, nano::logger &); void start (); void stop (); @@ -374,10 +380,10 @@ class websocket_server nano::wallets & wallets; nano::ledger & ledger; boost::asio::io_context & io_ctx; - nano::logger_mt & logger; + nano::logger & logger; public: // TODO: Encapsulate, this is public just because existing code needs it std::shared_ptr server; }; -} +} // namespace nano diff --git a/nano/node/websocket_stream.cpp b/nano/node/websocket_stream.cpp index 74d5eaf8a3..d680e999d2 100644 --- a/nano/node/websocket_stream.cpp +++ b/nano/node/websocket_stream.cpp @@ -67,6 +67,11 @@ class stream_wrapper : public nano::websocket::websocket_stream_concept return strand; } + socket_type & get_socket () override + { + return ws.next_layer (); + } + void close (boost::beast::websocket::close_reason const & reason_a, boost::system::error_code & ec_a) override { ws.close (reason_a, ec_a); @@ -105,6 +110,11 @@ nano::websocket::stream::stream (socket_type socket_a) return impl->get_strand (); } +[[nodiscard]] socket_type & nano::websocket::stream::get_socket () +{ + return impl->get_socket (); +} + void nano::websocket::stream::handshake (std::function callback_a) { impl->handshake (callback_a); diff --git a/nano/node/websocket_stream.hpp b/nano/node/websocket_stream.hpp index 03e21490ce..5a5cb86c45 100644 --- a/nano/node/websocket_stream.hpp +++ b/nano/node/websocket_stream.hpp @@ -32,6 +32,7 @@ class websocket_stream_concept public: virtual ~websocket_stream_concept () = default; virtual boost::asio::strand & get_strand () = 0; + virtual socket_type & get_socket () = 0; virtual void handshake (std::function callback_a) = 0; virtual void close (boost::beast::websocket::close_reason const & reason_a, boost::system::error_code & ec_a) = 0; virtual void async_write (nano::shared_const_buffer const & buffer_a, std::function callback_a) = 0; @@ -51,6 +52,7 @@ class stream final : public websocket_stream_concept stream (socket_type socket_a); [[nodiscard]] boost::asio::strand & get_strand () override; + [[nodiscard]] socket_type & get_socket () override; void handshake (std::function callback_a) override; void close (boost::beast::websocket::close_reason const & reason_a, boost::system::error_code & ec_a) override; void async_write (nano::shared_const_buffer const & buffer_a, std::function callback_a) override; diff --git a/nano/qt/qt.cpp b/nano/qt/qt.cpp index 2c8b6cfb1b..2b07123e27 100644 --- a/nano/qt/qt.cpp +++ b/nano/qt/qt.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include @@ -521,36 +523,47 @@ class short_text_visitor : public nano::block_visitor { type = "Send"; account = block_a.hashables.destination; - bool error_or_pruned (false); - amount = ledger.amount_safe (transaction, block_a.hash (), error_or_pruned); - if (error_or_pruned) + auto amount_l = ledger.amount (transaction, block_a.hash ()); + if (!amount_l) { type = "Send (pruned)"; } + else + { + amount = amount_l.value (); + } } void receive_block (nano::receive_block const & block_a) { type = "Receive"; - bool error_or_pruned (false); - account = ledger.account_safe (transaction, block_a.hashables.source, error_or_pruned); - amount = ledger.amount_safe (transaction, block_a.hash (), error_or_pruned); - if (error_or_pruned) + auto account_l = ledger.account (transaction, block_a.hashables.source); + auto amount_l = ledger.amount (transaction, block_a.hash ()); + if (!account_l || !amount_l) { type = "Receive (pruned)"; } + else + { + account = account_l.value (); + amount = amount_l.value (); + } } void open_block (nano::open_block const & block_a) { type = "Receive"; if (block_a.hashables.source != ledger.constants.genesis->account ()) { - bool error_or_pruned (false); - account = ledger.account_safe (transaction, block_a.hashables.source, error_or_pruned); - amount = ledger.amount_safe (transaction, block_a.hash (), error_or_pruned); - if (error_or_pruned) + auto account_l = ledger.account (transaction, block_a.hashables.source); + auto amount_l = ledger.amount (transaction, block_a.hash ()); + if (!account_l || !amount_l) { type = "Receive (pruned)"; } + else + { + account = account_l.value (); + amount = amount_l.value (); + } } else { @@ -567,9 +580,8 @@ class short_text_visitor : public nano::block_visitor void state_block (nano::state_block const & block_a) { auto balance (block_a.hashables.balance.number ()); - bool error_or_pruned (false); - auto previous_balance (ledger.balance_safe (transaction, block_a.hashables.previous, error_or_pruned)); - if (error_or_pruned) + auto previous_balance = ledger.balance (transaction, block_a.hashables.previous); + if (!previous_balance) { type = "Unknown (pruned)"; amount = 0; @@ -578,7 +590,7 @@ class short_text_visitor : public nano::block_visitor else if (balance < previous_balance) { type = "Send"; - amount = previous_balance - balance; + amount = previous_balance.value () - balance; account = block_a.hashables.link.as_account (); } else @@ -596,20 +608,24 @@ class short_text_visitor : public nano::block_visitor else { type = "Receive"; - account = ledger.account_safe (transaction, block_a.hashables.link.as_block_hash (), error_or_pruned); - if (error_or_pruned) + auto account_l = ledger.account (transaction, block_a.hashables.link.as_block_hash ()); + if (!account_l) { type = "Receive (pruned)"; } + else + { + account = account_l.value (); + } } - amount = balance - previous_balance; + amount = balance - previous_balance.value (); } } nano::store::transaction const & transaction; nano::ledger & ledger; std::string type; nano::uint128_t amount; - nano::account account; + nano::account account{ 0 }; }; } @@ -622,7 +638,7 @@ void nano_qt::history::refresh () for (auto i (0), n (tx_count->value ()); i < n && !hash.is_zero (); ++i) { QList items; - auto block (ledger.store.block.get (transaction, hash)); + auto block (ledger.block (transaction, hash)); if (block != nullptr) { block->visit (visitor); @@ -671,7 +687,7 @@ nano_qt::block_viewer::block_viewer (nano_qt::wallet & wallet_a) : if (!hash_l.decode_hex (hash->text ().toStdString ())) { auto transaction (this->wallet.node.store.tx_begin_read ()); - auto block_l (this->wallet.node.store.block.get (transaction, hash_l)); + auto block_l (this->wallet.node.ledger.block (transaction, hash_l)); if (block_l != nullptr) { std::string contents; @@ -696,7 +712,7 @@ nano_qt::block_viewer::block_viewer (nano_qt::wallet & wallet_a) : if (!error) { auto transaction (this->wallet.node.store.tx_begin_read ()); - if (this->wallet.node.store.block.exists (transaction, block)) + if (this->wallet.node.ledger.block_exists (transaction, block)) { rebroadcast->setEnabled (false); this->wallet.node.background ([this, block] () { @@ -717,7 +733,7 @@ void nano_qt::block_viewer::rebroadcast_action (nano::block_hash const & hash_a) { auto done (true); auto transaction (wallet.node.ledger.store.tx_begin_read ()); - auto block (wallet.node.store.block.get (transaction, hash_a)); + auto block (wallet.node.ledger.block (transaction, hash_a)); if (block != nullptr) { wallet.node.network.flood_block (block); @@ -1546,7 +1562,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) : retype_password->setPlaceholderText ("Retype password"); show_button_success (*change); change->setText ("Password was changed"); - this->wallet.node.logger.try_log ("Wallet password changed"); + this->wallet.node.logger.warn (nano::log::type::qt, "Wallet password changed"); update_locked (false, false); this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { @@ -1639,7 +1655,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) : this->wallet.wallet_m->store.password.value_set (empty); update_locked (true, true); lock_toggle->setText ("Unlock"); - this->wallet.node.logger.try_log ("Wallet locked"); + this->wallet.node.logger.warn (nano::log::type::qt, "Wallet locked"); password->setEnabled (1); } else @@ -2238,7 +2254,7 @@ void nano_qt::block_creation::create_send () details.is_send = true; details.epoch = info.epoch (); auto const required_difficulty{ wallet.node.network_params.work.threshold (send.work_version (), details) }; - if (wallet.node.work_generate_blocking (send, required_difficulty).is_initialized ()) + if (wallet.node.work_generate_blocking (send, required_difficulty).has_value ()) { std::string block_l; send.serialize_json (block_l); @@ -2299,15 +2315,14 @@ void nano_qt::block_creation::create_receive () { auto transaction (wallet.node.wallets.tx_begin_read ()); auto block_transaction (wallet.node.store.tx_begin_read ()); - auto block_l (wallet.node.store.block.get (block_transaction, source_l)); + auto block_l (wallet.node.ledger.block (block_transaction, source_l)); if (block_l != nullptr) { - auto const & destination (wallet.node.ledger.block_destination (block_transaction, *block_l)); + auto destination = block_l->destination (); if (!destination.is_zero ()) { nano::pending_key pending_key (destination, source_l); - nano::pending_info pending; - if (!wallet.node.store.pending.get (block_transaction, pending_key, pending)) + if (auto pending = wallet.node.store.pending.get (block_transaction, pending_key)) { nano::account_info info; auto error (wallet.node.store.account.get (block_transaction, pending_key.account, info)); @@ -2317,12 +2332,12 @@ void nano_qt::block_creation::create_receive () auto error (wallet.wallet_m->store.fetch (transaction, pending_key.account, key)); if (!error) { - nano::state_block receive (pending_key.account, info.head, info.representative, info.balance.number () + pending.amount.number (), source_l, key, pending_key.account, 0); + nano::state_block receive (pending_key.account, info.head, info.representative, info.balance.number () + pending.value ().amount.number (), source_l, key, pending_key.account, 0); nano::block_details details; details.is_receive = true; - details.epoch = std::max (info.epoch (), pending.epoch); + details.epoch = std::max (info.epoch (), pending.value ().epoch); auto required_difficulty{ wallet.node.network_params.work.threshold (receive.work_version (), details) }; - if (wallet.node.work_generate_blocking (receive, required_difficulty).is_initialized ()) + if (wallet.node.work_generate_blocking (receive, required_difficulty).has_value ()) { std::string block_l; receive.serialize_json (block_l); @@ -2405,7 +2420,7 @@ void nano_qt::block_creation::create_change () nano::block_details details; details.epoch = info.epoch (); auto const required_difficulty{ wallet.node.network_params.work.threshold (change.work_version (), details) }; - if (wallet.node.work_generate_blocking (change, required_difficulty).is_initialized ()) + if (wallet.node.work_generate_blocking (change, required_difficulty).has_value ()) { std::string block_l; change.serialize_json (block_l); @@ -2464,15 +2479,14 @@ void nano_qt::block_creation::create_open () { auto transaction (wallet.node.wallets.tx_begin_read ()); auto block_transaction (wallet.node.store.tx_begin_read ()); - auto block_l (wallet.node.store.block.get (block_transaction, source_l)); + auto block_l (wallet.node.ledger.block (block_transaction, source_l)); if (block_l != nullptr) { - auto const & destination (wallet.node.ledger.block_destination (block_transaction, *block_l)); + auto destination = block_l->destination (); if (!destination.is_zero ()) { nano::pending_key pending_key (destination, source_l); - nano::pending_info pending; - if (!wallet.node.store.pending.get (block_transaction, pending_key, pending)) + if (auto pending = wallet.node.store.pending.get (block_transaction, pending_key)) { nano::account_info info; auto error (wallet.node.store.account.get (block_transaction, pending_key.account, info)); @@ -2482,12 +2496,12 @@ void nano_qt::block_creation::create_open () auto error (wallet.wallet_m->store.fetch (transaction, pending_key.account, key)); if (!error) { - nano::state_block open (pending_key.account, 0, representative_l, pending.amount, source_l, key, pending_key.account, 0); + nano::state_block open (pending_key.account, 0, representative_l, pending.value ().amount, source_l, key, pending_key.account, 0); nano::block_details details; details.is_receive = true; - details.epoch = pending.epoch; + details.epoch = pending.value ().epoch; auto const required_difficulty{ wallet.node.network_params.work.threshold (open.work_version (), details) }; - if (wallet.node.work_generate_blocking (open, required_difficulty).is_initialized ()) + if (wallet.node.work_generate_blocking (open, required_difficulty).has_value ()) { std::string block_l; open.serialize_json (block_l); diff --git a/nano/qt_test/entry.cpp b/nano/qt_test/entry.cpp index 0352439ec6..e8976178c4 100644 --- a/nano/qt_test/entry.cpp +++ b/nano/qt_test/entry.cpp @@ -1,8 +1,10 @@ +#include #include #include #include + QApplication * test_application = nullptr; namespace nano { @@ -15,6 +17,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; QApplication application (argc, argv); diff --git a/nano/qt_test/qt.cpp b/nano/qt_test/qt.cpp index f7b1b41ae3..d6758ff883 100644 --- a/nano/qt_test/qt.cpp +++ b/nano/qt_test/qt.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include #include @@ -359,7 +361,7 @@ TEST (wallet, DISABLED_process_block) nano_qt::eventloop_processor processor; nano::test::system system (1); nano::account account; - nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis->account ())); + nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis_key.pub)); system.wallet (0)->insert_adhoc (nano::keypair ().prv); { auto transaction (system.nodes[0]->wallets.tx_begin_read ()); @@ -389,7 +391,7 @@ TEST (wallet, DISABLED_process_block) { auto transaction (system.nodes[0]->store.tx_begin_read ()); system.deadline_set (10s); - while (system.nodes[0]->store.block.exists (transaction, send.hash ())) + while (system.nodes[0]->ledger.block_exists (transaction, send.hash ())) { ASSERT_NO_ERROR (system.poll ()); } @@ -422,10 +424,10 @@ TEST (wallet, create_send) std::stringstream istream (json); boost::property_tree::read_json (istream, tree1); bool error (false); - nano::state_block send (error, tree1); + auto send = std::make_shared (error, tree1); ASSERT_FALSE (error); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (send).code); - ASSERT_EQ (nano::process_result::old, system.nodes[0]->process (send).code); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (send)); + ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (send)); } TEST (wallet, create_open_receive) @@ -456,10 +458,10 @@ TEST (wallet, create_open_receive) std::stringstream istream1 (json1); boost::property_tree::read_json (istream1, tree1); bool error (false); - nano::state_block open (error, tree1); + auto open = std::make_shared (error, tree1); ASSERT_FALSE (error); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (open).code); - ASSERT_EQ (nano::process_result::old, system.nodes[0]->process (open).code); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (open)); + ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (open)); wallet->block_creation.block->clear (); wallet->block_creation.source->clear (); wallet->block_creation.receive->click (); @@ -471,10 +473,10 @@ TEST (wallet, create_open_receive) std::stringstream istream2 (json2); boost::property_tree::read_json (istream2, tree2); bool error2 (false); - nano::state_block receive (error2, tree2); + auto receive = std::make_shared (error2, tree2); ASSERT_FALSE (error2); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (receive).code); - ASSERT_EQ (nano::process_result::old, system.nodes[0]->process (receive).code); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (receive)); + ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (receive)); } TEST (wallet, create_change) @@ -499,10 +501,10 @@ TEST (wallet, create_change) std::stringstream istream (json); boost::property_tree::read_json (istream, tree1); bool error (false); - nano::state_block change (error, tree1); + auto change = std::make_shared (error, tree1); ASSERT_FALSE (error); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (change).code); - ASSERT_EQ (nano::process_result::old, system.nodes[0]->process (change).code); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (change)); + ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (change)); } TEST (history, short_text) @@ -522,7 +524,8 @@ TEST (history, short_text) account = system.account (transaction, 0); } auto wallet (std::make_shared (*test_application, processor, *system.nodes[0], system.wallet (0), account)); - auto store = nano::make_store (system.nodes[0]->logger, nano::unique_path (), nano::dev::constants); + nano::logger logger; + auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::ledger ledger (*store, system.nodes[0]->stats, nano::dev::constants); { @@ -530,12 +533,12 @@ TEST (history, short_text) store->initialize (transaction, ledger.cache, ledger.constants); nano::keypair key; auto latest (ledger.latest (transaction, nano::dev::genesis_key.pub)); - nano::send_block send (latest, nano::dev::genesis_key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); - nano::receive_block receive (send.hash (), send.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send.hash ())); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); - nano::change_block change (receive.hash (), key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (receive.hash ())); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code); + auto send = std::make_shared (latest, nano::dev::genesis_key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); + auto receive = std::make_shared (send->hash (), send->hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); + auto change = std::make_shared (receive->hash (), key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (receive->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change)); } nano_qt::history history (ledger, nano::dev::genesis_key.pub, *wallet); history.refresh (); @@ -559,7 +562,8 @@ TEST (history, pruned_source) account = system.account (transaction, 0); } auto wallet (std::make_shared (*test_application, processor, *system.nodes[0], system.wallet (0), account)); - auto store = nano::make_store (system.nodes[0]->logger, nano::unique_path (), nano::dev::constants); + nano::logger logger; + auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); nano::ledger ledger (*store, system.nodes[0]->stats, nano::dev::constants); ledger.pruning = true; @@ -569,16 +573,16 @@ TEST (history, pruned_source) auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, nano::dev::constants); auto latest (ledger.latest (transaction, nano::dev::genesis_key.pub)); - nano::send_block send1 (latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 100, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send1).code); - nano::send_block send2 (send1.hash (), key.pub, nano::dev::constants.genesis_amount - 200, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send1.hash ())); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send2).code); - nano::receive_block receive (send2.hash (), send1.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send2.hash ())); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); - nano::open_block open (send2.hash (), key.pub, key.pub, key.prv, key.pub, *system.work.generate (key.pub)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, open).code); - ASSERT_EQ (1, ledger.pruning_action (transaction, send1.hash (), 2)); - next_pruning = send2.hash (); + auto send1 = std::make_shared (latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 100, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); + auto send2 = std::make_shared (send1->hash (), key.pub, nano::dev::constants.genesis_amount - 200, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send1->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2)); + auto receive = std::make_shared (send2->hash (), send1->hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send2->hash ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); + auto open = std::make_shared (send2->hash (), key.pub, key.pub, key.prv, key.pub, *system.work.generate (key.pub)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); + ASSERT_EQ (1, ledger.pruning_action (transaction, send1->hash (), 2)); + next_pruning = send2->hash (); } nano_qt::history history1 (ledger, nano::dev::genesis_key.pub, *wallet); history1.refresh (); @@ -599,11 +603,11 @@ TEST (history, pruned_source) { auto transaction (store->tx_begin_write ()); auto latest (ledger.latest (transaction, nano::dev::genesis_key.pub)); - nano::state_block send (nano::dev::genesis_key.pub, latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 200, key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); + auto send = std::make_shared (nano::dev::genesis_key.pub, latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 200, key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto latest_key (ledger.latest (transaction, key.pub)); - nano::state_block receive (key.pub, latest_key, key.pub, 200, send.hash (), key.prv, key.pub, *system.work.generate (latest_key)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); + auto receive = std::make_shared (key.pub, latest_key, key.pub, 200, send->hash (), key.prv, key.pub, *system.work.generate (latest_key)); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); ASSERT_EQ (1, ledger.pruning_action (transaction, latest, 2)); ASSERT_EQ (1, ledger.pruning_action (transaction, latest_key, 2)); } @@ -662,7 +666,7 @@ TEST (wallet, block_viewer) ASSERT_NE (-1, wallet->advanced.layout->indexOf (wallet->advanced.block_viewer)); QTest::mouseClick (wallet->advanced.block_viewer, Qt::LeftButton); ASSERT_EQ (wallet->block_viewer.window, wallet->main_stack->currentWidget ()); - nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis->account ())); + nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis_key.pub)); QTest::keyClicks (wallet->block_viewer.hash, latest.to_string ().c_str ()); QTest::mouseClick (wallet->block_viewer.retrieve, Qt::LeftButton); ASSERT_FALSE (wallet->block_viewer.block->toPlainText ().toStdString ().empty ()); @@ -683,7 +687,7 @@ TEST (wallet, import) system.wallet (0)->store.serialize_json (transaction, json); } system.wallet (1)->insert_adhoc (key2.prv); - auto path (nano::unique_path ()); + auto path{ nano::unique_path () / "wallet.json" }; { std::ofstream stream; stream.open (path.string ().c_str ()); @@ -714,9 +718,9 @@ TEST (wallet, republish) { auto transaction (system.nodes[0]->store.tx_begin_write ()); auto latest (system.nodes[0]->ledger.latest (transaction, nano::dev::genesis_key.pub)); - nano::send_block block (latest, key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); - hash = block.hash (); - ASSERT_EQ (nano::process_result::progress, system.nodes[0]->ledger.process (transaction, block).code); + auto block = std::make_shared (latest, key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest)); + hash = block->hash (); + ASSERT_EQ (nano::block_status::progress, system.nodes[0]->ledger.process (transaction, block)); } auto account (nano::dev::genesis_key.pub); auto wallet (std::make_shared (*test_application, processor, *system.nodes[0], system.wallet (0), account)); @@ -913,8 +917,8 @@ TEST (wallet, DISABLED_synchronizing) wallet->start (); { auto transaction (system1.nodes[0]->store.tx_begin_write ()); - auto latest (system1.nodes[0]->ledger.latest (transaction, nano::dev::genesis->account ())); - nano::send_block send (latest, key1, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system1.work.generate (latest)); + auto latest (system1.nodes[0]->ledger.latest (transaction, nano::dev::genesis_key.pub)); + auto send = std::make_shared (latest, key1, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system1.work.generate (latest)); system1.nodes[0]->ledger.process (transaction, send); } ASSERT_EQ (0, wallet->active_status.active.count (nano_qt::status_types::synchronizing)); @@ -963,10 +967,10 @@ TEST (wallet, epoch_2_validation) std::stringstream istream (json); boost::property_tree::read_json (istream, tree1); bool error (false); - nano::state_block block (error, tree1); + auto block = std::make_shared (error, tree1); EXPECT_FALSE (error); - EXPECT_EQ (nano::process_result::progress, node->process (block).code); - return block.hash (); + EXPECT_EQ (nano::block_status::progress, node->process (block)); + return block->hash (); }; auto do_send = [&] (nano::public_key const & destination) -> nano::block_hash { diff --git a/nano/rpc/rpc.cpp b/nano/rpc/rpc.cpp index 18c0e5a227..687c9b316e 100644 --- a/nano/rpc/rpc.cpp +++ b/nano/rpc/rpc.cpp @@ -15,7 +15,6 @@ nano::rpc::rpc (boost::asio::io_context & io_ctx_a, nano::rpc_config config_a, nano::rpc_handler_interface & rpc_handler_interface_a) : config (std::move (config_a)), acceptor (io_ctx_a), - logger (std::chrono::milliseconds (0)), io_ctx (io_ctx_a), rpc_handler_interface (rpc_handler_interface_a) { @@ -33,13 +32,13 @@ nano::rpc::~rpc () void nano::rpc::start () { auto endpoint (boost::asio::ip::tcp::endpoint (boost::asio::ip::make_address_v6 (config.address), config.port)); + bool const is_loopback = (endpoint.address ().is_loopback () || (endpoint.address ().to_v6 ().is_v4_mapped () && boost::asio::ip::make_address_v4 (boost::asio::ip::v4_mapped, endpoint.address ().to_v6 ()).is_loopback ())); if (!is_loopback && config.enable_control) { - auto warning = boost::str (boost::format ("WARNING: control-level RPCs are enabled on non-local address %1%, potentially allowing wallet access outside local computer") % endpoint.address ().to_string ()); - std::cout << warning << std::endl; - logger.always_log (warning); + logger.warn (nano::log::type::rpc, "WARNING: Control-level RPCs are enabled on non-local address {}, potentially allowing wallet access outside local computer", endpoint.address ().to_string ()); } + acceptor.open (endpoint.protocol ()); acceptor.set_option (boost::asio::ip::tcp::acceptor::reuse_address (true)); @@ -47,7 +46,7 @@ void nano::rpc::start () acceptor.bind (endpoint, ec); if (ec) { - logger.always_log (boost::str (boost::format ("Error while binding for RPC on port %1%: %2%") % endpoint.port () % ec.message ())); + logger.critical (nano::log::type::rpc, "Error while binding for RPC on port: {} ({})", endpoint.port (), ec.message ()); throw std::runtime_error (ec.message ()); } acceptor.listen (); @@ -68,7 +67,7 @@ void nano::rpc::accept () } else { - logger.always_log (boost::str (boost::format ("Error accepting RPC connections: %1% (%2%)") % ec.message () % ec.value ())); + logger.error (nano::log::type::rpc, "Error accepting RPC connection: {}", ec.message ()); } })); } diff --git a/nano/rpc/rpc.hpp b/nano/rpc/rpc.hpp index 40c096f37c..99f66b260a 100644 --- a/nano/rpc/rpc.hpp +++ b/nano/rpc/rpc.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -31,9 +31,9 @@ class rpc return acceptor.local_endpoint ().port (); } + nano::logger logger{ "rpc" }; nano::rpc_config config; boost::asio::ip::tcp::acceptor acceptor; - nano::logger_mt logger; boost::asio::io_context & io_ctx; nano::rpc_handler_interface & rpc_handler_interface; bool stopped{ false }; diff --git a/nano/rpc/rpc_connection.cpp b/nano/rpc/rpc_connection.cpp index f4d96be45b..d7c71562c1 100644 --- a/nano/rpc/rpc_connection.cpp +++ b/nano/rpc/rpc_connection.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -14,7 +13,7 @@ #endif #include -nano::rpc_connection::rpc_connection (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger_mt & logger, nano::rpc_handler_interface & rpc_handler_interface) : +nano::rpc_connection::rpc_connection (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger & logger, nano::rpc_handler_interface & rpc_handler_interface) : socket (io_ctx), strand (io_ctx.get_executor ()), io_ctx (io_ctx), @@ -84,7 +83,7 @@ void nano::rpc_connection::read (STREAM_TYPE & stream) } else { - this_l->logger.always_log ("RPC header error: ", ec.message ()); + this_l->logger.error (nano::log::type::rpc_connection, "RPC header error: ", ec.message ()); // Respond with the reason for the invalid header auto response_handler ([this_l, &stream] (std::string const & tree_a) { @@ -123,12 +122,9 @@ void nano::rpc_connection::parse_request (STREAM_TYPE & stream, std::shared_ptr< this_l->write_completion_handler (this_l); })); - std::stringstream ss; - if (this_l->rpc_config.rpc_logging.log_rpc) - { - ss << "RPC request " << request_id << " completed in: " << std::chrono::duration_cast (std::chrono::steady_clock::now () - start).count () << " microseconds"; - this_l->logger.always_log (ss.str ().c_str ()); - } + // Bump logging level if RPC request logging is enabled + this_l->logger.log (this_l->rpc_config.rpc_logging.log_rpc ? nano::log::level::info : nano::log::level::debug, + nano::log::type::rpc_request, "RPC request {} completed in {} microseconds", request_id, std::chrono::duration_cast (std::chrono::steady_clock::now () - start).count ()); }); std::string api_path_l = "/api/v2"; @@ -168,7 +164,7 @@ void nano::rpc_connection::parse_request (STREAM_TYPE & stream, std::shared_ptr< } else { - this_l->logger.always_log ("RPC read error: ", ec.message ()); + this_l->logger.error (nano::log::type::rpc_connection, "RPC read error: ", ec.message ()); } })); } diff --git a/nano/rpc/rpc_connection.hpp b/nano/rpc/rpc_connection.hpp index 3226e28064..960e0b31fa 100644 --- a/nano/rpc/rpc_connection.hpp +++ b/nano/rpc/rpc_connection.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -18,14 +19,13 @@ using socket_type = boost::asio::basic_stream_socket { public: - rpc_connection (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger_mt & logger, nano::rpc_handler_interface & rpc_handler_interface_a); + rpc_connection (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger &, nano::rpc_handler_interface & rpc_handler_interface_a); virtual ~rpc_connection () = default; virtual void parse_connection (); virtual void write_completion_handler (std::shared_ptr const & rpc_connection); @@ -38,7 +38,7 @@ class rpc_connection : public std::enable_shared_from_this boost::asio::strand strand; std::atomic_flag responded; boost::asio::io_context & io_ctx; - nano::logger_mt & logger; + nano::logger & logger; nano::rpc_config const & rpc_config; nano::rpc_handler_interface & rpc_handler_interface; diff --git a/nano/rpc/rpc_handler.cpp b/nano/rpc/rpc_handler.cpp index 7148d45d63..241c46c47c 100644 --- a/nano/rpc/rpc_handler.cpp +++ b/nano/rpc/rpc_handler.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -18,7 +17,7 @@ std::unordered_set rpc_control_impl_set = create_rpc_control_impls std::string filter_request (boost::property_tree::ptree tree_a); } -nano::rpc_handler::rpc_handler (nano::rpc_config const & rpc_config, std::string const & body_a, std::string const & request_id_a, std::function const & response_a, nano::rpc_handler_interface & rpc_handler_interface_a, nano::logger_mt & logger) : +nano::rpc_handler::rpc_handler (nano::rpc_config const & rpc_config, std::string const & body_a, std::string const & request_id_a, std::function const & response_a, nano::rpc_handler_interface & rpc_handler_interface_a, nano::logger & logger) : body (body_a), request_id (request_id_a), response (response_a), @@ -62,13 +61,10 @@ void nano::rpc_handler::process_request (nano::rpc_handler_request_params const } auto action = request.get ("action"); - if (rpc_config.rpc_logging.log_rpc) - { - // Creating same string via stringstream as using it directly is generating a TSAN warning - std::stringstream ss; - ss << request_id; - logger.always_log (ss.str (), " ", filter_request (request)); - } + + // Bump logging level if RPC request logging is enabled + logger.log (rpc_config.rpc_logging.log_rpc ? nano::log::level::info : nano::log::level::debug, + nano::log::type::rpc_request, "Request {} : {}", request_id, filter_request (request)); // Check if this is a RPC command which requires RPC enabled control std::error_code rpc_control_disabled_ec = nano::error_rpc::rpc_control_disabled; diff --git a/nano/rpc/rpc_handler.hpp b/nano/rpc/rpc_handler.hpp index 2e919f303a..55a979fa07 100644 --- a/nano/rpc/rpc_handler.hpp +++ b/nano/rpc/rpc_handler.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -9,13 +11,12 @@ namespace nano { class rpc_config; class rpc_handler_interface; -class logger_mt; class rpc_handler_request_params; class rpc_handler : public std::enable_shared_from_this { public: - rpc_handler (nano::rpc_config const & rpc_config, std::string const & body_a, std::string const & request_id_a, std::function const & response_a, nano::rpc_handler_interface & rpc_handler_interface_a, nano::logger_mt & logger); + rpc_handler (nano::rpc_config const & rpc_config, std::string const & body_a, std::string const & request_id_a, std::function const & response_a, nano::rpc_handler_interface & rpc_handler_interface_a, nano::logger &); void process_request (nano::rpc_handler_request_params const & request_params); private: @@ -25,6 +26,6 @@ class rpc_handler : public std::enable_shared_from_this std::function response; nano::rpc_config const & rpc_config; nano::rpc_handler_interface & rpc_handler_interface; - nano::logger_mt & logger; + nano::logger & logger; }; } diff --git a/nano/rpc/rpc_secure.cpp b/nano/rpc/rpc_secure.cpp index 3f596a7cba..9640e28c2f 100644 --- a/nano/rpc/rpc_secure.cpp +++ b/nano/rpc/rpc_secure.cpp @@ -27,7 +27,7 @@ void nano::rpc_secure::accept () } else { - logger.always_log (boost::str (boost::format ("Error accepting RPC connections: %1%") % ec)); + logger.error (nano::log::type::rpc, "Error accepting RPC connection: {}", ec.message ()); } })); } diff --git a/nano/rpc_test/entry.cpp b/nano/rpc_test/entry.cpp index 530f146c98..2a94b7d9e7 100644 --- a/nano/rpc_test/entry.cpp +++ b/nano/rpc_test/entry.cpp @@ -1,7 +1,9 @@ +#include #include #include #include + namespace nano { namespace test @@ -13,6 +15,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::set_use_memory_pools (false); nano::node_singleton_memory_pool_purge_guard cleanup_guard; diff --git a/nano/rpc_test/receivable.cpp b/nano/rpc_test/receivable.cpp index 61dd352d35..e73221bd52 100644 --- a/nano/rpc_test/receivable.cpp +++ b/nano/rpc_test/receivable.cpp @@ -1,7 +1,9 @@ +#include #include #include #include #include +#include #include #include #include @@ -20,7 +22,7 @@ TEST (rpc, receivable) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); auto response = wait_response (system, rpc_ctx, request); auto & blocks_node = response.get_child ("blocks"); ASSERT_EQ (1, blocks_node.size ()); @@ -38,7 +40,7 @@ TEST (rpc, receivable_sorting) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); request.put ("sorting", "true"); // Sorting test auto response = wait_response (system, rpc_ctx, request); auto & blocks_node = response.get_child ("blocks"); @@ -59,7 +61,7 @@ TEST (rpc, receivable_threshold_sufficient) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); request.put ("threshold", "1"); // Threshold test auto response = wait_response (system, rpc_ctx, request); auto & blocks_node = response.get_child ("blocks"); @@ -90,7 +92,7 @@ TEST (rpc, receivable_threshold_insufficient) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); request.put ("threshold", "2"); // Chains are set up with 1 raw transfers therefore all blocks are less than 2 raw. auto response = wait_response (system, rpc_ctx, request, 10s); auto & blocks_node = response.get_child ("blocks"); @@ -107,7 +109,7 @@ TEST (rpc, receivable_source_min_version) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); request.put ("source", "true"); request.put ("min_version", "true"); auto response (wait_response (system, rpc_ctx, request)); @@ -139,14 +141,14 @@ TEST (rpc, receivable_unconfirmed) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "receivable"); - request.put ("account", block1->link ().to_account ()); + request.put ("account", block1->destination ().to_account ()); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 0)); request.put ("include_only_confirmed", "true"); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 0)); request.put ("include_only_confirmed", "false"); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 1)); ASSERT_TRUE (nano::test::start_elections (system, *node, { block1->hash () }, true)); - ASSERT_TIMELY (5s, !node->active.active (*block1)); + ASSERT_TIMELY (5s, nano::test::confirmed (*node, { block1 })); request.put ("include_only_confirmed", "true"); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 1)); } @@ -196,7 +198,7 @@ TEST (rpc, receivable_offset_and_sorting) // check confirmation height is as expected, there is no perfect clarity yet when confirmation height updates after a block get confirmed nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (node->store.confirmation_height.get (node->store.tx_begin_read (), nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE (node->store.confirmation_height.get (node->store.tx_begin_read (), nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (confirmation_height_info.height, 7); ASSERT_EQ (confirmation_height_info.frontier, block6->hash ()); @@ -370,7 +372,7 @@ TEST (rpc, search_receivable) .build (); { auto transaction (node->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, block)); } auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -409,14 +411,14 @@ TEST (rpc, accounts_receivable_blocks) request.put ("action", "accounts_receivable"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", block1->link ().to_account ()); + entry.put ("", block1->destination ().to_account ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("accounts", peers_l); auto response = wait_response (system, rpc_ctx, request); for (auto & blocks : response.get_child ("blocks")) { std::string account_text{ blocks.first }; - ASSERT_EQ (block1->link ().to_account (), account_text); + ASSERT_EQ (block1->destination ().to_account (), account_text); nano::block_hash hash1{ blocks.second.begin ()->second.get ("") }; ASSERT_EQ (block1->hash (), hash1); } @@ -435,7 +437,7 @@ TEST (rpc, accounts_receivable_sorting) request.put ("action", "accounts_receivable"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", block1->link ().to_account ()); + entry.put ("", block1->destination ().to_account ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("accounts", peers_l); request.put ("sorting", "true"); // Sorting test @@ -443,7 +445,7 @@ TEST (rpc, accounts_receivable_sorting) for (auto & blocks : response.get_child ("blocks")) { std::string account_text{ blocks.first }; - ASSERT_EQ (block1->link ().to_account (), account_text); + ASSERT_EQ (block1->destination ().to_account (), account_text); nano::block_hash hash1{ blocks.second.begin ()->first }; ASSERT_EQ (block1->hash (), hash1); std::string amount{ blocks.second.begin ()->second.get ("") }; @@ -464,7 +466,7 @@ TEST (rpc, accounts_receivable_threshold) request.put ("action", "accounts_receivable"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", block1->link ().to_account ()); + entry.put ("", block1->destination ().to_account ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("accounts", peers_l); request.put ("threshold", "1"); // Threshold test @@ -473,7 +475,7 @@ TEST (rpc, accounts_receivable_threshold) for (auto & pending : response.get_child ("blocks")) { std::string account_text{ pending.first }; - ASSERT_EQ (block1->link ().to_account (), account_text); + ASSERT_EQ (block1->destination ().to_account (), account_text); for (auto i (pending.second.begin ()), j (pending.second.end ()); i != j; ++i) { nano::block_hash hash; @@ -500,7 +502,7 @@ TEST (rpc, accounts_receivable_source) request.put ("action", "accounts_receivable"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", block1->link ().to_account ()); + entry.put ("", block1->destination ().to_account ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("accounts", peers_l); request.put ("source", "true"); @@ -511,7 +513,7 @@ TEST (rpc, accounts_receivable_source) for (auto & pending : response.get_child ("blocks")) { std::string account_text (pending.first); - ASSERT_EQ (block1->link ().to_account (), account_text); + ASSERT_EQ (block1->destination ().to_account (), account_text); for (auto i (pending.second.begin ()), j (pending.second.end ()); i != j; ++i) { nano::block_hash hash; @@ -533,14 +535,13 @@ TEST (rpc, accounts_receivable_confirmed) auto node = add_ipc_enabled_node (system, config); auto chain = nano::test::setup_chain (system, *node, 1, nano::dev::genesis_key, false); auto block1 = chain[0]; - ASSERT_TIMELY (5s, !node->active.active (*block1)); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "accounts_receivable"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", block1->link ().to_account ()); + entry.put ("", block1->destination ().to_account ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("accounts", peers_l); @@ -550,7 +551,7 @@ TEST (rpc, accounts_receivable_confirmed) request.put ("include_only_confirmed", "false"); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 1)); ASSERT_TRUE (nano::test::start_elections (system, *node, { block1->hash () }, true)); - ASSERT_TIMELY (5s, !node->active.active (*block1)); + ASSERT_TIMELY (5s, nano::test::confirmed (*node, { block1 })); request.put ("include_only_confirmed", "true"); ASSERT_TRUE (check_block_response_count (system, rpc_ctx, request, 1)); } diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 056d05a1b7..7ca31f1649 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -72,7 +74,7 @@ TEST (rpc, account_balance) .work (*system.work.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node->process (send1)); ASSERT_TIMELY (5s, !node->active.active (*send1)); auto const rpc_ctx = add_rpc (system, node); @@ -152,7 +154,7 @@ TEST (rpc, account_weight) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*block).code); + ASSERT_EQ (nano::block_status::progress, node1->process (block)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "account_weight"); @@ -504,7 +506,7 @@ TEST (rpc, wallet_representative) request.put ("action", "wallet_representative"); auto response (wait_response (system, rpc_ctx, request)); std::string account_text1 (response.get ("representative")); - ASSERT_EQ (account_text1, nano::dev::genesis->account ().to_account ()); + ASSERT_EQ (account_text1, nano::dev::genesis_key.pub.to_account ()); } TEST (rpc, wallet_representative_set) @@ -662,7 +664,7 @@ TEST (rpc, wallet_export) bool error (false); auto transaction (node->wallets.tx_begin_write ()); nano::kdf kdf{ nano::dev::network_params.kdf_work }; - nano::wallet_store store (error, kdf, transaction, node->wallets.env, nano::dev::genesis->account (), 1, "0", wallet_json); + nano::wallet_store store (error, kdf, transaction, node->wallets.env, nano::dev::genesis_key.pub, 1, "0", wallet_json); ASSERT_FALSE (error); ASSERT_TRUE (store.exists (transaction, nano::dev::genesis_key.pub)); } @@ -717,7 +719,7 @@ TEST (rpc, block) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "block"); - request.put ("hash", node->latest (nano::dev::genesis->account ()).to_string ()); + request.put ("hash", node->latest (nano::dev::genesis_key.pub).to_string ()); auto response (wait_response (system, rpc_ctx, request)); auto contents (response.get ("contents")); ASSERT_FALSE (contents.empty ()); @@ -922,24 +924,24 @@ TEST (rpc, history) ASSERT_NE (nullptr, change); auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, node0->config.receive_minimum.number ())); ASSERT_NE (nullptr, send); - auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node0->config.receive_minimum.number (), send->link ().as_account ())); + auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node0->config.receive_minimum.number (), send->destination ())); ASSERT_NE (nullptr, receive); nano::block_builder builder; auto usend = builder .state () - .account (nano::dev::genesis->account ()) - .previous (node0->latest (nano::dev::genesis->account ())) - .representative (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) + .previous (node0->latest (nano::dev::genesis_key.pub)) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*node0->work_generate_blocking (node0->latest (nano::dev::genesis->account ()))) + .work (*node0->work_generate_blocking (node0->latest (nano::dev::genesis_key.pub))) .build (); auto ureceive = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (usend->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (usend->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -947,7 +949,7 @@ TEST (rpc, history) .build (); auto uchange = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (ureceive->hash ()) .representative (nano::keypair ().pub) .balance (nano::dev::constants.genesis_amount) @@ -957,9 +959,9 @@ TEST (rpc, history) .build (); { auto transaction (node0->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *usend).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *ureceive).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *uchange).code); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, usend)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, ureceive)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, uchange)); } auto const rpc_ctx = add_rpc (system, node0); boost::property_tree::ptree request; @@ -1006,24 +1008,24 @@ TEST (rpc, account_history) ASSERT_NE (nullptr, change); auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, node0->config.receive_minimum.number ())); ASSERT_NE (nullptr, send); - auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node0->config.receive_minimum.number (), send->link ().as_account ())); + auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node0->config.receive_minimum.number (), send->destination ())); ASSERT_NE (nullptr, receive); nano::block_builder builder; auto usend = builder .state () - .account (nano::dev::genesis->account ()) - .previous (node0->latest (nano::dev::genesis->account ())) - .representative (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) + .previous (node0->latest (nano::dev::genesis_key.pub)) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*node0->work_generate_blocking (node0->latest (nano::dev::genesis->account ()))) + .work (*node0->work_generate_blocking (node0->latest (nano::dev::genesis_key.pub))) .build (); auto ureceive = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (usend->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (usend->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -1031,7 +1033,7 @@ TEST (rpc, account_history) .build (); auto uchange = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (ureceive->hash ()) .representative (nano::keypair ().pub) .balance (nano::dev::constants.genesis_amount) @@ -1041,15 +1043,15 @@ TEST (rpc, account_history) .build (); { auto transaction (node0->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *usend).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *ureceive).code); - ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, *uchange).code); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, usend)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, ureceive)); + ASSERT_EQ (nano::block_status::progress, node0->ledger.process (transaction, uchange)); } auto const rpc_ctx = add_rpc (system, node0); { boost::property_tree::ptree request; request.put ("action", "account_history"); - request.put ("account", nano::dev::genesis->account ().to_account ()); + request.put ("account", nano::dev::genesis_key.pub.to_account ()); request.put ("count", 100); auto response (wait_response (system, rpc_ctx, request, 10s)); std::vector> history_l; @@ -1095,7 +1097,7 @@ TEST (rpc, account_history) { boost::property_tree::ptree request; request.put ("action", "account_history"); - request.put ("account", nano::dev::genesis->account ().to_account ()); + request.put ("account", nano::dev::genesis_key.pub.to_account ()); request.put ("reverse", true); request.put ("count", 1); auto response (wait_response (system, rpc_ctx, request, 10s)); @@ -1109,7 +1111,7 @@ TEST (rpc, account_history) auto account2 (system.wallet (0)->deterministic_insert ()); auto send2 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, account2, node0->config.receive_minimum.number ())); ASSERT_NE (nullptr, send2); - auto receive2 (system.wallet (0)->receive_action (send2->hash (), account2, node0->config.receive_minimum.number (), send2->link ().as_account ())); + auto receive2 (system.wallet (0)->receive_action (send2->hash (), account2, node0->config.receive_minimum.number (), send2->destination ())); // Test filter for send state blocks ASSERT_NE (nullptr, receive2); { @@ -1152,7 +1154,7 @@ TEST (rpc, history_count) ASSERT_NE (nullptr, change); auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, node->config.receive_minimum.number ())); ASSERT_NE (nullptr, send); - auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node->config.receive_minimum.number (), send->link ().as_account ())); + auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node->config.receive_minimum.number (), send->destination ())); ASSERT_NE (nullptr, receive); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -1183,7 +1185,7 @@ TEST (rpc, history_pruning) .representative (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); blocks.push_back (change); // legacy send to itself @@ -1194,7 +1196,7 @@ TEST (rpc, history_pruning) .balance (nano::dev::constants.genesis_amount - node0->config.receive_minimum.number ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work.generate (change->hash ())) - .build_shared (); + .build (); blocks.push_back (send); // legacy receive the legacy self send @@ -1204,46 +1206,46 @@ TEST (rpc, history_pruning) .source (send->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work.generate (send->hash ())) - .build_shared (); + .build (); blocks.push_back (receive); // non legacy self send auto usend = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (receive->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis->account ()) + .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (receive->hash ())) - .build_shared (); + .build (); blocks.push_back (usend); // non legacy receive of the non legacy self send auto ureceive = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (usend->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount) .link (usend->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (usend->hash ())) - .build_shared (); + .build (); blocks.push_back (ureceive); // change genesis to a random rep auto uchange = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (ureceive->hash ()) .representative (nano::keypair ().pub) .balance (nano::dev::constants.genesis_amount) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node0->work_generate_blocking (ureceive->hash ())) - .build_shared (); + .build (); blocks.push_back (uchange); nano::test::process_live (*node0, blocks); @@ -1438,7 +1440,7 @@ TEST (rpc, process_block_async) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); std::string json1; state_send->serialize_json (json1); request.put ("block", json1); @@ -1513,9 +1515,9 @@ TEST (rpc, process_subtype_send) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -1549,16 +1551,16 @@ TEST (rpc, process_subtype_open) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); - ASSERT_EQ (nano::process_result::progress, node2.process (*send).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); + ASSERT_EQ (nano::block_status::progress, node2.process (send)); auto const rpc_ctx = add_rpc (system, node1); node1->scheduler.manual.push (send); auto open = builder @@ -1598,16 +1600,16 @@ TEST (rpc, process_subtype_receive) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); - ASSERT_EQ (nano::process_result::progress, node2.process (*send).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); + ASSERT_EQ (nano::block_status::progress, node2.process (send)); auto const rpc_ctx = add_rpc (system, node1); node1->scheduler.manual.push (send); auto receive = builder @@ -1651,9 +1653,9 @@ TEST (rpc, process_ledger_insufficient_work) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (latest) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -1677,7 +1679,7 @@ TEST (rpc, keepalive) { nano::test::system system; auto node0 = add_ipc_enabled_node (system); - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); node1->start (); system.nodes.push_back (node1); auto const rpc_ctx = add_rpc (system, node0); @@ -2087,9 +2089,9 @@ TEST (rpc, work_peer_bad) auto const rpc_ctx = add_rpc (system, node1); nano::block_hash hash1 (1); std::atomic work (0); - node2.work_generate (nano::work_version::work_1, hash1, node2.network_params.work.base, [&work] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); - work = *work_a; + node2.work_generate (nano::work_version::work_1, hash1, node2.network_params.work.base, [&work] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); + work = work_a.value (); }); ASSERT_TIMELY (5s, nano::dev::network_params.work.difficulty (nano::work_version::work_1, hash1, work) >= nano::dev::network_params.work.threshold_base (nano::work_version::work_1)); } @@ -2106,9 +2108,9 @@ TEST (rpc, DISABLED_work_peer_one) node2.config.work_peers.emplace_back (node1->network.endpoint ().address ().to_string (), rpc_ctx.rpc->listening_port ()); nano::keypair key1; std::atomic work (0); - node2.work_generate (nano::work_version::work_1, key1.pub, node1->network_params.work.base, [&work] (boost::optional work_a) { - ASSERT_TRUE (work_a.is_initialized ()); - work = *work_a; + node2.work_generate (nano::work_version::work_1, key1.pub, node1->network_params.work.base, [&work] (std::optional work_a) { + ASSERT_TRUE (work_a.has_value ()); + work = work_a.value (); }); ASSERT_TIMELY (5s, nano::dev::network_params.work.difficulty (nano::work_version::work_1, key1.pub, work) >= nano::dev::network_params.work.threshold_base (nano::work_version::work_1)); } @@ -2137,7 +2139,7 @@ TEST (rpc, DISABLED_work_peer_many) for (auto & work : works) { nano::keypair key1; - node1.work_generate (nano::work_version::work_1, key1.pub, node1.network_params.work.base, [&work] (boost::optional work_a) { + node1.work_generate (nano::work_version::work_1, key1.pub, node1.network_params.work.base, [&work] (std::optional work_a) { work = *work_a; }); while (nano::dev::network_params.work.difficulty (nano::work_version::work_1, key1.pub, work) < nano::dev::network_params.work.threshold_base (nano::work_version::work_1)) @@ -2227,16 +2229,16 @@ TEST (rpc, block_count_pruning) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) - .build_shared (); - node1->process_active (send1); + .build (); + node1->process_local (send1); auto receive1 = builder .receive () .previous (send1->hash ()) .source (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send1->hash ())) - .build_shared (); - node1->process_active (receive1); + .build (); + node1->process_local (receive1); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); ASSERT_TIMELY (5s, node1->block_confirmed (receive1->hash ())); // Pruning action @@ -2376,11 +2378,11 @@ TEST (rpc, account_representative) auto node = add_ipc_enabled_node (system); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; - request.put ("account", nano::dev::genesis->account ().to_account ()); + request.put ("account", nano::dev::genesis_key.pub.to_account ()); request.put ("action", "account_representative"); auto response (wait_response (system, rpc_ctx, request)); std::string account_text1 (response.get ("representative")); - ASSERT_EQ (account_text1, nano::dev::genesis->account ().to_account ()); + ASSERT_EQ (account_text1, nano::dev::genesis_key.pub.to_account ()); } TEST (rpc, account_representative_set) @@ -2395,8 +2397,8 @@ TEST (rpc, account_representative_set) wallet.insert_adhoc (key2.prv); auto key2_open_block_hash = wallet.send_sync (nano::dev::genesis_key.pub, key2.pub, node->config.receive_minimum.number ()); ASSERT_TIMELY (5s, node->ledger.block_confirmed (node->store.tx_begin_read (), key2_open_block_hash)); - auto key2_open_block = node->store.block.get (node->store.tx_begin_read (), key2_open_block_hash); - ASSERT_EQ (nano::dev::genesis_key.pub, key2_open_block->representative ()); + auto key2_open_block = node->ledger.block (node->store.tx_begin_read (), key2_open_block_hash); + ASSERT_EQ (nano::dev::genesis_key.pub, key2_open_block->representative_field ().value ()); // now change the representative of key2 to be genesis auto const rpc_ctx = add_rpc (system, node); @@ -2412,10 +2414,10 @@ TEST (rpc, account_representative_set) nano::block_hash hash; ASSERT_FALSE (hash.decode_hex (block_text1)); ASSERT_FALSE (hash.is_zero ()); - auto block = node->store.block.get (node->store.tx_begin_read (), hash); + auto block = node->ledger.block (node->store.tx_begin_read (), hash); ASSERT_NE (block, nullptr); ASSERT_TIMELY (5s, node->ledger.block_confirmed (node->store.tx_begin_read (), hash)); - ASSERT_EQ (key2.pub, block->representative ()); + ASSERT_EQ (key2.pub, block->representative_field ().value ()); } TEST (rpc, account_representative_set_work_disabled) @@ -2428,7 +2430,7 @@ TEST (rpc, account_representative_set_work_disabled) auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; nano::keypair rep; - request.put ("account", nano::dev::genesis->account ().to_account ()); + request.put ("account", nano::dev::genesis_key.pub.to_account ()); request.put ("representative", rep.pub.to_account ()); request.put ("wallet", node->wallets.items.begin ()->first.to_string ()); request.put ("action", "account_representative_set"); @@ -2490,14 +2492,14 @@ TEST (rpc, bootstrap) auto send = builder .send () .previous (latest) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); { auto transaction (node1->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node1->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node1->ledger.process (transaction, send)); } auto const rpc_ctx = add_rpc (system0, node); boost::property_tree::ptree request; @@ -2510,7 +2512,7 @@ TEST (rpc, bootstrap) system0.poll (); } system1.deadline_set (10s); - while (node->latest (nano::dev::genesis->account ()) != node1->latest (nano::dev::genesis->account ())) + while (node->latest (nano::dev::genesis_key.pub) != node1->latest (nano::dev::genesis_key.pub)) { ASSERT_NO_ERROR (system0.poll ()); ASSERT_NO_ERROR (system1.poll ()); @@ -2549,7 +2551,7 @@ TEST (rpc, representatives) representatives.push_back (account); } ASSERT_EQ (1, representatives.size ()); - ASSERT_EQ (nano::dev::genesis->account (), representatives[0]); + ASSERT_EQ (nano::dev::genesis_key.pub, representatives[0]); } // wallet_seed is only available over IPC's unsafe encoding, and when running on test network @@ -2625,7 +2627,7 @@ TEST (rpc, wallet_frontiers) frontiers.push_back (nano::account (i->second.get (""))); } ASSERT_EQ (1, frontiers.size ()); - ASSERT_EQ (node->latest (nano::dev::genesis->account ()), frontiers[0]); + ASSERT_EQ (node->latest (nano::dev::genesis_key.pub), frontiers[0]); } TEST (rpc, work_validate) @@ -2775,14 +2777,14 @@ TEST (rpc, bootstrap_any) auto send = builder .send () .previous (latest) - .destination (nano::dev::genesis->account ()) + .destination (nano::dev::genesis_key.pub) .balance (100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system1.nodes[0]->work_generate_blocking (latest)) .build (); { auto transaction (system1.nodes[0]->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, system1.nodes[0]->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, system1.nodes[0]->ledger.process (transaction, send)); } auto const rpc_ctx = add_rpc (system0, node); boost::property_tree::ptree request; @@ -2808,7 +2810,7 @@ TEST (rpc, republish) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -2817,7 +2819,7 @@ TEST (rpc, republish) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "republish"); @@ -2995,10 +2997,10 @@ TEST (rpc, accounts_balances_unopened_account_with_receivables) .link (unopened_account.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } ASSERT_TIMELY (5s, node->block (send->hash ())); ASSERT_TIMELY (5s, !node->active.active (*send)); @@ -3050,8 +3052,8 @@ TEST (rpc, accounts_representatives) request.add_child ("accounts", accounts); auto response (wait_response (system, rpc_ctx, request)); // Ensures the response is correct. - auto response_representative (response.get_child ("representatives").get (nano::dev::genesis->account ().to_account ())); - ASSERT_EQ (response_representative, nano::dev::genesis->account ().to_account ()); + auto response_representative (response.get_child ("representatives").get (nano::dev::genesis_key.pub.to_account ())); + ASSERT_EQ (response_representative, nano::dev::genesis_key.pub.to_account ()); ASSERT_EQ (response.count ("errors"), 0); } @@ -3092,7 +3094,7 @@ TEST (rpc, accounts_representatives_with_errors) ASSERT_EQ (response.get_child ("representatives").size (), 1); ASSERT_EQ (response.get_child ("representatives").count (nano::dev::genesis_key.pub.to_account ()), 1); auto rep_text = response.get_child ("representatives").get (nano::dev::genesis_key.pub.to_account ()); - ASSERT_EQ (rep_text, nano::dev::genesis->account ().to_account ()); + ASSERT_EQ (rep_text, nano::dev::genesis_key.pub.to_account ()); ASSERT_EQ (response.count ("errors"), 1); ASSERT_EQ (response.get_child ("errors").size (), 2); @@ -3125,7 +3127,7 @@ TEST (rpc, accounts_frontiers) ASSERT_EQ (response.get_child ("frontiers").size (), 1); ASSERT_EQ (response.get_child ("frontiers").count (nano::dev::genesis_key.pub.to_account ()), 1); auto frontier_text = response.get_child ("frontiers").get (nano::dev::genesis_key.pub.to_account ()); - ASSERT_EQ (nano::block_hash{ frontier_text }, node->latest (nano::dev::genesis->account ())); + ASSERT_EQ (nano::block_hash{ frontier_text }, node->latest (nano::dev::genesis_key.pub)); ASSERT_EQ (response.count ("errors"), 0); } @@ -3165,7 +3167,7 @@ TEST (rpc, accounts_frontiers_with_errors) ASSERT_EQ (response.get_child ("frontiers").size (), 1); ASSERT_EQ (response.get_child ("frontiers").count (nano::dev::genesis_key.pub.to_account ()), 1); auto frontier_text = response.get_child ("frontiers").get (nano::dev::genesis_key.pub.to_account ()); - ASSERT_EQ (nano::block_hash{ frontier_text }, node->latest (nano::dev::genesis->account ())); + ASSERT_EQ (nano::block_hash{ frontier_text }, node->latest (nano::dev::genesis_key.pub)); ASSERT_EQ (response.count ("errors"), 1); ASSERT_EQ (response.get_child ("errors").size (), 2); @@ -3184,14 +3186,14 @@ TEST (rpc, blocks) request.put ("action", "blocks"); boost::property_tree::ptree entry; boost::property_tree::ptree peers_l; - entry.put ("", node->latest (nano::dev::genesis->account ()).to_string ()); + entry.put ("", node->latest (nano::dev::genesis_key.pub).to_string ()); peers_l.push_back (std::make_pair ("", entry)); request.add_child ("hashes", peers_l); auto response (wait_response (system, rpc_ctx, request)); for (auto & blocks : response.get_child ("blocks")) { std::string hash_text (blocks.first); - ASSERT_EQ (node->latest (nano::dev::genesis->account ()).to_string (), hash_text); + ASSERT_EQ (node->latest (nano::dev::genesis_key.pub).to_string (), hash_text); std::string blocks_text (blocks.second.get ("")); ASSERT_FALSE (blocks_text.empty ()); } @@ -3290,7 +3292,7 @@ TEST (rpc, pending_exists) auto node = add_ipc_enabled_node (system, config); nano::keypair key1; system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); - auto hash0 (node->latest (nano::dev::genesis->account ())); + auto hash0 (node->latest (nano::dev::genesis_key.pub)); auto block1 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key1.pub, 100)); ASSERT_TIMELY (5s, node->block_confirmed (block1->hash ())); ASSERT_TIMELY (5s, !node->active.active (*block1)); @@ -3466,7 +3468,7 @@ TEST (rpc, work_get) std::string work_text (response.get ("work")); uint64_t work (1); auto transaction (node->wallets.tx_begin_read ()); - node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis->account (), work); + node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis_key.pub, work); ASSERT_EQ (nano::to_string_hex (work), work_text); } @@ -3488,7 +3490,7 @@ TEST (rpc, wallet_work_get) ASSERT_EQ (nano::dev::genesis_key.pub.to_account (), account_text); std::string work_text (works.second.get ("")); uint64_t work (1); - node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis->account (), work); + node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis_key.pub, work); ASSERT_EQ (nano::to_string_hex (work), work_text); } } @@ -3510,7 +3512,7 @@ TEST (rpc, work_set) ASSERT_TRUE (success.empty ()); uint64_t work1 (1); auto transaction (node->wallets.tx_begin_read ()); - node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis->account (), work1); + node->wallets.items.begin ()->second->store.work_get (transaction, nano::dev::genesis_key.pub, work1); ASSERT_EQ (work1, work0); } @@ -3531,7 +3533,7 @@ TEST (rpc, search_receivable_all) .build (); { auto transaction (node->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, block)); } auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -3563,7 +3565,7 @@ TEST (rpc, wallet_republish) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -3572,7 +3574,7 @@ TEST (rpc, wallet_republish) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "wallet_republish"); @@ -3607,7 +3609,7 @@ TEST (rpc, delegators) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -3616,7 +3618,7 @@ TEST (rpc, delegators) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "delegators"); @@ -3648,7 +3650,7 @@ TEST (rpc, delegators_parameters) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -3657,7 +3659,7 @@ TEST (rpc, delegators_parameters) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto const rpc_ctx = add_rpc (system, node1); // Test with "count" = 2 @@ -3758,7 +3760,7 @@ TEST (rpc, delegators_count) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -3767,7 +3769,7 @@ TEST (rpc, delegators_count) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "delegators_count"); @@ -3810,7 +3812,7 @@ TEST (rpc, account_info) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto time = nano::seconds_since_epoch (); { auto transaction = node1->store.tx_begin_write (); @@ -3869,7 +3871,7 @@ TEST (rpc, account_info) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto send2 = builder .send () .previous (send1->hash ()) @@ -3878,7 +3880,7 @@ TEST (rpc, account_info) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send1->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); auto state_change = builder .state () @@ -3890,7 +3892,7 @@ TEST (rpc, account_info) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send2->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*state_change).code); + ASSERT_EQ (nano::block_status::progress, node1->process (state_change)); auto open = builder .open () @@ -3900,7 +3902,7 @@ TEST (rpc, account_info) .sign (key1.prv, key1.pub) .work (*node1->work_generate_blocking (key1.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); ASSERT_TIMELY (5s, !node1->active.active (*state_change)); ASSERT_TIMELY (5s, !node1->active.active (*open)); } @@ -3972,9 +3974,9 @@ TEST (rpc, json_block_input) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (node1->latest (nano::dev::genesis_key.pub)) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -4018,7 +4020,7 @@ TEST (rpc, json_block_output) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "block_info"); @@ -4041,7 +4043,7 @@ TEST (rpc, blocks_info) for (auto & blocks : response.get_child ("blocks")) { std::string hash_text (blocks.first); - ASSERT_EQ (node->latest (nano::dev::genesis->account ()).to_string (), hash_text); + ASSERT_EQ (node->latest (nano::dev::genesis_key.pub).to_string (), hash_text); std::string account_text (blocks.second.get ("block_account")); ASSERT_EQ (nano::dev::genesis_key.pub.to_account (), account_text); std::string amount_text (blocks.second.get ("amount")); @@ -4065,7 +4067,7 @@ TEST (rpc, blocks_info) request.put ("action", "blocks_info"); boost::property_tree::ptree entry; boost::property_tree::ptree hashes; - entry.put ("", node->latest (nano::dev::genesis->account ()).to_string ()); + entry.put ("", node->latest (nano::dev::genesis_key.pub).to_string ()); hashes.push_back (std::make_pair ("", entry)); request.add_child ("hashes", hashes); { @@ -4125,10 +4127,10 @@ TEST (rpc, blocks_info_receive_hash) auto send4 = system.wallet (0)->send_action (nano::dev::genesis_key.pub, key1.pub, 4); // do 4 receives, mix up the ordering a little - auto recv1 (system.wallet (0)->receive_action (send1->hash (), key1.pub, node->config.receive_minimum.number (), send1->link ().as_account ())); - auto recv4 (system.wallet (0)->receive_action (send4->hash (), key1.pub, node->config.receive_minimum.number (), send4->link ().as_account ())); - auto recv3 (system.wallet (0)->receive_action (send3->hash (), key1.pub, node->config.receive_minimum.number (), send3->link ().as_account ())); - auto recv2 (system.wallet (0)->receive_action (send2->hash (), key1.pub, node->config.receive_minimum.number (), send2->link ().as_account ())); + auto recv1 (system.wallet (0)->receive_action (send1->hash (), key1.pub, node->config.receive_minimum.number (), send1->destination ())); + auto recv4 (system.wallet (0)->receive_action (send4->hash (), key1.pub, node->config.receive_minimum.number (), send4->destination ())); + auto recv3 (system.wallet (0)->receive_action (send3->hash (), key1.pub, node->config.receive_minimum.number (), send3->destination ())); + auto recv2 (system.wallet (0)->receive_action (send2->hash (), key1.pub, node->config.receive_minimum.number (), send2->destination ())); // function to check that all 4 receive blocks are cemented auto all_blocks_cemented = [node, &key1] () -> bool { @@ -4191,7 +4193,7 @@ TEST (rpc, blocks_info_subtype) system.wallet (0)->insert_adhoc (key.prv); auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, nano::Gxrb_ratio)); ASSERT_NE (nullptr, send); - auto receive (system.wallet (0)->receive_action (send->hash (), key.pub, nano::Gxrb_ratio, send->link ().as_account ())); + auto receive (system.wallet (0)->receive_action (send->hash (), key.pub, nano::Gxrb_ratio, send->destination ())); ASSERT_NE (nullptr, receive); auto change (system.wallet (0)->change_action (nano::dev::genesis_key.pub, key.pub)); ASSERT_NE (nullptr, change); @@ -4240,7 +4242,7 @@ TEST (rpc, block_info_successor) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; request.put ("action", "block_info"); @@ -4276,7 +4278,7 @@ TEST (rpc, block_info_pruning) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) - .build_shared (); + .build (); node1->process_active (send1); auto receive1 = builder .receive () @@ -4284,7 +4286,7 @@ TEST (rpc, block_info_pruning) .source (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); node1->process_active (receive1); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); ASSERT_TIMELY (5s, node1->block_confirmed (receive1->hash ())); @@ -4292,7 +4294,7 @@ TEST (rpc, block_info_pruning) { auto transaction (node1->store.tx_begin_write ()); ASSERT_EQ (1, node1->ledger.pruning_action (transaction, send1->hash (), 1)); - ASSERT_TRUE (node1->store.block.exists (transaction, receive1->hash ())); + ASSERT_TRUE (node1->ledger.block_exists (transaction, receive1->hash ())); } auto const rpc_ctx = add_rpc (system, node1); // Pruned block @@ -4342,7 +4344,7 @@ TEST (rpc, pruned_exists) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) - .build_shared (); + .build (); node1->process_active (send1); auto receive1 = builder .receive () @@ -4350,7 +4352,7 @@ TEST (rpc, pruned_exists) .source (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send1->hash ())) - .build_shared (); + .build (); node1->process_active (receive1); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); ASSERT_TIMELY (5s, node1->block_confirmed (receive1->hash ())); @@ -4358,7 +4360,7 @@ TEST (rpc, pruned_exists) { auto transaction (node1->store.tx_begin_write ()); ASSERT_EQ (1, node1->ledger.pruning_action (transaction, send1->hash (), 1)); - ASSERT_TRUE (node1->store.block.exists (transaction, receive1->hash ())); + ASSERT_TRUE (node1->ledger.block_exists (transaction, receive1->hash ())); } auto const rpc_ctx = add_rpc (system, node1); // Pruned block @@ -4430,8 +4432,7 @@ TEST (rpc, populate_backlog) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*send).code); - ASSERT_FALSE (node->block_arrival.recent (send->hash ())); + ASSERT_EQ (nano::block_status::progress, node->process (send)); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -4462,7 +4463,7 @@ TEST (rpc, ledger) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node->process (send)); auto open = builder .open () .source (send->hash ()) @@ -4471,7 +4472,7 @@ TEST (rpc, ledger) .sign (key.prv, key.pub) .work (*node->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node->process (open)); auto time = nano::seconds_since_epoch (); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -4545,7 +4546,7 @@ TEST (rpc, ledger) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node->work_generate_blocking (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node->process (send2)); // When asking for pending, pending amount is taken into account for threshold so the account must show up request.put ("count", 2); request.put ("threshold", (send_amount + send2_amount).convert_to ()); @@ -4632,7 +4633,7 @@ TEST (rpc, block_create) boost::property_tree::read_json (block_stream, block_l); auto send_block (nano::deserialize_block_json (block_l)); ASSERT_EQ (send->hash (), send_block->hash ()); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); boost::property_tree::ptree request1; request1.put ("action", "block_create"); request1.put ("type", "open"); @@ -4650,7 +4651,7 @@ TEST (rpc, block_create) boost::property_tree::read_json (block_stream1, block_l); auto open_block (nano::deserialize_block_json (block_l)); ASSERT_EQ (open->hash (), open_block->hash ()); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); request1.put ("representative", key.pub.to_account ()); auto response2 (wait_response (system, rpc_ctx, request1)); std::string open2_hash (response2.get ("hash")); @@ -4673,7 +4674,7 @@ TEST (rpc, block_create) boost::property_tree::read_json (block_stream4, block_l); auto change_block (nano::deserialize_block_json (block_l)); ASSERT_EQ (change->hash (), change_block->hash ()); - ASSERT_EQ (nano::process_result::progress, node1->process (*change).code); + ASSERT_EQ (nano::block_status::progress, node1->process (change)); auto send2 = builder .send () .previous (send->hash ()) @@ -4682,7 +4683,7 @@ TEST (rpc, block_create) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (send->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send2)); boost::property_tree::ptree request2; request2.put ("action", "block_create"); request2.put ("type", "receive"); @@ -4730,8 +4731,8 @@ TEST (rpc, block_create_state) ASSERT_NE (nullptr, state_block); ASSERT_EQ (nano::block_type::state, state_block->type ()); ASSERT_EQ (state_hash, state_block->hash ().to_string ()); - auto process_result (node->process (*state_block)); - ASSERT_EQ (nano::process_result::progress, process_result.code); + auto process_result (node->process (state_block)); + ASSERT_EQ (nano::block_status::progress, process_result); } TEST (rpc, block_create_state_open) @@ -4766,10 +4767,10 @@ TEST (rpc, block_create_state_open) auto difficulty (nano::dev::network_params.work.difficulty (*state_block)); ASSERT_GT (difficulty, nano::dev::network_params.work.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_0, false, true, false))); ASSERT_TRUE (node->latest (key.pub).is_zero ()); - auto process_result (node->process (*state_block)); - ASSERT_EQ (nano::process_result::progress, process_result.code); + auto process_result (node->process (state_block)); + ASSERT_EQ (nano::block_status::progress, process_result); ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_0); - ASSERT_TRUE (state_block->sideband ().details.is_receive); + ASSERT_TRUE (state_block->is_receive ()); ASSERT_FALSE (node->latest (key.pub).is_zero ()); } @@ -4778,7 +4779,7 @@ TEST (rpc, block_create_state_request_work) { // Test work generation for state blocks both with and without previous (in the latter // case, the account will be used for work generation) - std::unique_ptr epoch2; + std::shared_ptr epoch2; { nano::test::system system (1); system.upgrade_genesis_epoch (*system.nodes.front (), nano::epoch::epoch_1); @@ -4845,10 +4846,10 @@ TEST (rpc, block_create_open_epoch_v2) auto difficulty (nano::dev::network_params.work.difficulty (*state_block)); ASSERT_GT (difficulty, nano::dev::network_params.work.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false))); ASSERT_TRUE (node->latest (key.pub).is_zero ()); - auto process_result (node->process (*state_block)); - ASSERT_EQ (nano::process_result::progress, process_result.code); + auto process_result (node->process (state_block)); + ASSERT_EQ (nano::block_status::progress, process_result); ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2); - ASSERT_TRUE (state_block->sideband ().details.is_receive); + ASSERT_TRUE (state_block->is_receive ()); ASSERT_FALSE (node->latest (key.pub).is_zero ()); } @@ -4872,7 +4873,7 @@ TEST (rpc, block_create_receive_epoch_v2) .sign (key.prv, key.pub) .work (*node->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node->process (open)); ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2)); auto send_block_2 (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, nano::Gxrb_ratio)); auto const rpc_ctx = add_rpc (system, node); @@ -4897,10 +4898,10 @@ TEST (rpc, block_create_receive_epoch_v2) ASSERT_EQ (state_hash, state_block->hash ().to_string ()); auto difficulty (nano::dev::network_params.work.difficulty (*state_block)); ASSERT_GT (difficulty, nano::dev::network_params.work.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false))); - auto process_result (node->process (*state_block)); - ASSERT_EQ (nano::process_result::progress, process_result.code); + auto process_result (node->process (state_block)); + ASSERT_EQ (nano::block_status::progress, process_result); ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2); - ASSERT_TRUE (state_block->sideband ().details.is_receive); + ASSERT_TRUE (state_block->is_receive ()); ASSERT_FALSE (node->latest (key.pub).is_zero ()); } @@ -4925,7 +4926,7 @@ TEST (rpc, block_create_send_epoch_v2) .sign (key.prv, key.pub) .work (*node->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node->process (open)); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "block_create"); @@ -4948,10 +4949,10 @@ TEST (rpc, block_create_send_epoch_v2) ASSERT_EQ (state_hash, state_block->hash ().to_string ()); auto difficulty (nano::dev::network_params.work.difficulty (*state_block)); ASSERT_GT (difficulty, nano::dev::network_params.work.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, true, false, false))); - auto process_result (node->process (*state_block)); - ASSERT_EQ (nano::process_result::progress, process_result.code); + auto process_result (node->process (state_block)); + ASSERT_EQ (nano::block_status::progress, process_result); ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2); - ASSERT_TRUE (state_block->sideband ().details.is_send); + ASSERT_TRUE (state_block->is_send ()); ASSERT_FALSE (node->latest (key.pub).is_zero ()); } @@ -5049,7 +5050,7 @@ TEST (rpc, wallet_ledger) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node1->work_generate_blocking (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); + ASSERT_EQ (nano::block_status::progress, node1->process (send)); auto open = builder .open () .source (send->hash ()) @@ -5058,7 +5059,7 @@ TEST (rpc, wallet_ledger) .sign (key.prv, key.pub) .work (*node1->work_generate_blocking (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); auto time = nano::seconds_since_epoch (); auto const rpc_ctx = add_rpc (system, node1); boost::property_tree::ptree request; @@ -5177,7 +5178,7 @@ TEST (rpc, online_reps) auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, new_rep, node1->config.receive_minimum.number ())); ASSERT_NE (nullptr, send); ASSERT_TIMELY (10s, node2->block (send->hash ())); - auto receive (system.wallet (1)->receive_action (send->hash (), new_rep, node1->config.receive_minimum.number (), send->link ().as_account ())); + auto receive (system.wallet (1)->receive_action (send->hash (), new_rep, node1->config.receive_minimum.number (), send->destination ())); ASSERT_NE (nullptr, receive); ASSERT_TIMELY (5s, node2->block (receive->hash ())); auto change (system.wallet (0)->change_action (nano::dev::genesis_key.pub, new_rep)); @@ -5222,14 +5223,14 @@ TEST (rpc, confirmation_height_currently_processing) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous_genesis_chain_hash)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); previous_genesis_chain_hash = send->hash (); } std::shared_ptr frontier; { auto transaction = node->store.tx_begin_read (); - frontier = node->store.block.get (transaction, previous_genesis_chain_hash); + frontier = node->ledger.block (transaction, previous_genesis_chain_hash); } boost::property_tree::ptree request; @@ -5341,10 +5342,10 @@ TEST (rpc, block_confirm) .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*node->work_generate_blocking (nano::dev::genesis->hash ())) - .build_shared (); + .build (); { auto transaction (node->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); } auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -5376,7 +5377,6 @@ TEST (rpc, block_confirm_confirmed) config.callback_address = "localhost"; config.callback_port = system.get_available_port (); config.callback_target = "/"; - config.logging.init (path); auto node = add_ipc_enabled_node (system, config); { auto transaction (node->store.tx_begin_read ()); @@ -5408,7 +5408,6 @@ TEST (rpc, node_id) boost::property_tree::ptree request; request.put ("action", "node_id"); auto response (wait_response (system, rpc_ctx, request)); - ASSERT_EQ (node->node_id.prv.to_string (), response.get ("private")); ASSERT_EQ (node->node_id.pub.to_account (), response.get ("as_account")); ASSERT_EQ (node->node_id.pub.to_node_id (), response.get ("node_id")); } @@ -5447,7 +5446,7 @@ TEST (rpc, unchecked) .link (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); auto open2 = builder .state () .account (key.pub) @@ -5457,7 +5456,7 @@ TEST (rpc, unchecked) .link (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); node->process_active (open); node->process_active (open2); // Waits for the last block of the queue to get saved in the database @@ -5499,7 +5498,7 @@ TEST (rpc, unchecked_get) .link (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); node->process_active (open); // Waits for the open block to get saved in the database ASSERT_TIMELY_EQ (10s, 1, node->unchecked.count ()); @@ -5538,7 +5537,7 @@ TEST (rpc, unchecked_clear) .link (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); node->process_active (open); boost::property_tree::ptree request{}; // Waits for the open block to get saved in the database @@ -5668,7 +5667,7 @@ TEST (rpc, DISABLED_wallet_history) auto send (system.wallet (0)->send_action (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, node->config.receive_minimum.number ())); ASSERT_NE (nullptr, send); auto timestamp2 = nano::seconds_since_epoch (); - auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node->config.receive_minimum.number (), send->link ().as_account ())); + auto receive (system.wallet (0)->receive_action (send->hash (), nano::dev::genesis_key.pub, node->config.receive_minimum.number (), send->destination ())); ASSERT_NE (nullptr, receive); nano::keypair key; auto timestamp3 = nano::seconds_since_epoch (); @@ -5721,9 +5720,9 @@ TEST (rpc, sign_hash) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (node1->latest (nano::dev::genesis_key.pub)) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -5754,9 +5753,9 @@ TEST (rpc, sign_block) nano::block_builder builder; auto send = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (node1->latest (nano::dev::genesis_key.pub)) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -5801,10 +5800,10 @@ TEST (rpc, memory_stats) .link (0) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); std::vector hashes; hashes.push_back (block->hash ()); - auto vote (std::make_shared (key.pub, key.prv, 0, 0, hashes)); + auto vote = nano::test::make_vote (key, { hashes }, 0, 0); node->vote_uniquer.unique (vote); boost::property_tree::ptree request; request.put ("action", "stats"); @@ -5852,17 +5851,17 @@ TEST (rpc, block_confirmed) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); auto open1 = builder .open () .source (send1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open1).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open1)); } // This should not be confirmed @@ -5879,7 +5878,7 @@ TEST (rpc, block_confirmed) .balance (10) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); node->process_active (send); ASSERT_TRUE (nano::test::start_elections (system, *node, { send }, true)); @@ -6145,8 +6144,8 @@ TEST (rpc, epoch_upgrade) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); // to opened account - ASSERT_EQ (nano::process_result::progress, node->process (*send1).code); + .build (); // to opened account + ASSERT_EQ (nano::block_status::progress, node->process (send1)); auto send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6156,8 +6155,8 @@ TEST (rpc, epoch_upgrade) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); // to unopened account (pending) - ASSERT_EQ (nano::process_result::progress, node->process (*send2).code); + .build (); // to unopened account (pending) + ASSERT_EQ (nano::block_status::progress, node->process (send2)); auto send3 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6167,8 +6166,8 @@ TEST (rpc, epoch_upgrade) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send2->hash ())) - .build_shared (); // to burn (0) - ASSERT_EQ (nano::process_result::progress, node->process (*send3).code); + .build (); // to burn (0) + ASSERT_EQ (nano::block_status::progress, node->process (send3)); nano::account max_account (std::numeric_limits::max ()); auto send4 = builder .state () @@ -6179,8 +6178,8 @@ TEST (rpc, epoch_upgrade) .link (max_account) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send3->hash ())) - .build_shared (); // to max account - ASSERT_EQ (nano::process_result::progress, node->process (*send4).code); + .build (); // to max account + ASSERT_EQ (nano::block_status::progress, node->process (send4)); auto open = builder .state () .account (key1.pub) @@ -6190,8 +6189,8 @@ TEST (rpc, epoch_upgrade) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->process (open)); // Check accounts epochs { auto transaction (node->store.tx_begin_read ()); @@ -6236,8 +6235,8 @@ TEST (rpc, epoch_upgrade) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (genesis_latest)) - .build_shared (); // to burn (0) - ASSERT_EQ (nano::process_result::progress, node->process (*send5).code); + .build (); // to burn (0) + ASSERT_EQ (nano::block_status::progress, node->process (send5)); auto send6 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6247,8 +6246,8 @@ TEST (rpc, epoch_upgrade) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send5->hash ())) - .build_shared (); // to key1 (again) - ASSERT_EQ (nano::process_result::progress, node->process (*send6).code); + .build (); // to key1 (again) + ASSERT_EQ (nano::block_status::progress, node->process (send6)); auto key1_latest (node->latest (key1.pub)); auto send7 = builder .state () @@ -6259,8 +6258,8 @@ TEST (rpc, epoch_upgrade) .link (key3.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_latest)) - .build_shared (); // to key3 - ASSERT_EQ (nano::process_result::progress, node->process (*send7).code); + .build (); // to key3 + ASSERT_EQ (nano::block_status::progress, node->process (send7)); { // Check pending entry auto transaction (node->store.tx_begin_read ()); @@ -6308,8 +6307,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); // to opened account - ASSERT_EQ (nano::process_result::progress, node->process (*send1).code); + .build (); // to opened account + ASSERT_EQ (nano::block_status::progress, node->process (send1)); auto send2 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6319,8 +6318,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); // to unopened account (pending) - ASSERT_EQ (nano::process_result::progress, node->process (*send2).code); + .build (); // to unopened account (pending) + ASSERT_EQ (nano::block_status::progress, node->process (send2)); auto send3 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6330,8 +6329,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send2->hash ())) - .build_shared (); // to burn (0) - ASSERT_EQ (nano::process_result::progress, node->process (*send3).code); + .build (); // to burn (0) + ASSERT_EQ (nano::block_status::progress, node->process (send3)); nano::account max_account (std::numeric_limits::max ()); auto send4 = builder .state () @@ -6342,8 +6341,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (max_account) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send3->hash ())) - .build_shared (); // to max account - ASSERT_EQ (nano::process_result::progress, node->process (*send4).code); + .build (); // to max account + ASSERT_EQ (nano::block_status::progress, node->process (send4)); auto open = builder .state () .account (key1.pub) @@ -6353,8 +6352,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (send1->hash ()) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->process (open)); // Check accounts epochs { auto transaction (node->store.tx_begin_read ()); @@ -6400,8 +6399,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (genesis_latest)) - .build_shared (); // to burn (0) - ASSERT_EQ (nano::process_result::progress, node->process (*send5).code); + .build (); // to burn (0) + ASSERT_EQ (nano::block_status::progress, node->process (send5)); auto send6 = builder .state () .account (nano::dev::genesis_key.pub) @@ -6411,8 +6410,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (key1.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send5->hash ())) - .build_shared (); // to key1 (again) - ASSERT_EQ (nano::process_result::progress, node->process (*send6).code); + .build (); // to key1 (again) + ASSERT_EQ (nano::block_status::progress, node->process (send6)); auto key1_latest (node->latest (key1.pub)); auto send7 = builder .state () @@ -6423,8 +6422,8 @@ TEST (rpc, epoch_upgrade_multithreaded) .link (key3.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1_latest)) - .build_shared (); // to key3 - ASSERT_EQ (nano::process_result::progress, node->process (*send7).code); + .build (); // to key3 + ASSERT_EQ (nano::block_status::progress, node->process (send7)); { // Check pending entry auto transaction (node->store.tx_begin_read ()); @@ -6472,8 +6471,8 @@ TEST (rpc, account_lazy_start) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (send1)); auto open = builder .open () .source (send1->hash ()) @@ -6481,8 +6480,8 @@ TEST (rpc, account_lazy_start) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node1->process (*open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node1->process (open)); // Start lazy bootstrap with account nano::node_config node_config = system.default_config (); @@ -6503,8 +6502,7 @@ TEST (rpc, account_lazy_start) // needs timed assert because the writing (put) operation is done by a different // thread, it might not get done before DB get operation. - ASSERT_TIMELY (10s, node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_TIMELY (10s, node2->ledger.block_or_pruned_exists (open->hash ())); + ASSERT_TIMELY (15s, nano::test::block_or_pruned_all_exists (*node2, { send1, open })); } TEST (rpc, receive) @@ -6561,7 +6559,7 @@ TEST (rpc, receive_unopened) auto send1 (wallet->send_action (nano::dev::genesis_key.pub, key1.pub, node->config.receive_minimum.number () - 1, *node->work_generate_blocking (nano::dev::genesis->hash ()))); ASSERT_TIMELY (5s, !node->balance (nano::dev::genesis_key.pub) != nano::dev::constants.genesis_amount); ASSERT_FALSE (node->store.account.exists (node->store.tx_begin_read (), key1.pub)); - ASSERT_TRUE (node->store.block.exists (node->store.tx_begin_read (), send1->hash ())); + ASSERT_TRUE (node->ledger.block_exists (node->store.tx_begin_read (), send1->hash ())); wallet->insert_adhoc (key1.prv); // should not auto receive, amount sent was lower than minimum auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -6585,7 +6583,7 @@ TEST (rpc, receive_unopened) auto send2 (wallet->send_action (nano::dev::genesis_key.pub, key2.pub, node->config.receive_minimum.number () - 1, *node->work_generate_blocking (send1->hash ()))); ASSERT_TIMELY (5s, !node->balance (nano::dev::genesis_key.pub) != prev_amount); ASSERT_FALSE (node->store.account.exists (node->store.tx_begin_read (), key2.pub)); - ASSERT_TRUE (node->store.block.exists (node->store.tx_begin_read (), send2->hash ())); + ASSERT_TRUE (node->ledger.block_exists (node->store.tx_begin_read (), send2->hash ())); nano::public_key rep; wallet->store.representative_set (node->wallets.tx_begin_write (), rep); wallet->insert_adhoc (key2.prv); // should not auto receive, amount sent was lower than minimum @@ -6617,10 +6615,10 @@ TEST (rpc, receive_work_disabled) nano::keypair key1; ASSERT_TRUE (worker_node.work_generation_enabled ()); auto send1 (wallet->send_action (nano::dev::genesis_key.pub, key1.pub, node->config.receive_minimum.number () - 1, *worker_node.work_generate_blocking (nano::dev::genesis->hash ()), false)); - ASSERT_TRUE (send1 != nullptr); + ASSERT_NE (send1, nullptr); ASSERT_TIMELY (5s, node->balance (nano::dev::genesis_key.pub) != nano::dev::constants.genesis_amount); ASSERT_FALSE (node->store.account.exists (node->store.tx_begin_read (), key1.pub)); - ASSERT_TRUE (node->store.block.exists (node->store.tx_begin_read (), send1->hash ())); + ASSERT_TRUE (node->ledger.block_exists (node->store.tx_begin_read (), send1->hash ())); wallet->insert_adhoc (key1.prv); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; @@ -6665,9 +6663,9 @@ TEST (rpc, receive_pruned) } ASSERT_EQ (2, node2->ledger.cache.pruned_count); ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send1->hash ())); - ASSERT_FALSE (node2->store.block.exists (node2->store.tx_begin_read (), send1->hash ())); + ASSERT_FALSE (node2->ledger.block_exists (node2->store.tx_begin_read (), send1->hash ())); ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send2->hash ())); - ASSERT_FALSE (node2->store.block.exists (node2->store.tx_begin_read (), send2->hash ())); + ASSERT_FALSE (node2->ledger.block_exists (node2->store.tx_begin_read (), send2->hash ())); ASSERT_TRUE (node2->ledger.block_or_pruned_exists (send3->hash ())); auto const rpc_ctx = add_rpc (system, node2); @@ -6872,7 +6870,7 @@ TEST (rpc, confirmation_active) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); auto send2 = builder .send () .previous (send1->hash ()) @@ -6880,7 +6878,7 @@ TEST (rpc, confirmation_active) .balance (nano::dev::constants.genesis_amount - 200) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (send1->hash ())) - .build_shared (); + .build (); node1->process_active (send1); node1->process_active (send2); ASSERT_TRUE (nano::test::start_elections (system, *node1, { send1, send2 })); @@ -6916,7 +6914,7 @@ TEST (rpc, confirmation_info) .balance (nano::dev::constants.genesis_amount - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); node1->process_active (send); ASSERT_TIMELY (5s, !node1->active.empty ()); diff --git a/nano/secure/CMakeLists.txt b/nano/secure/CMakeLists.txt index f80ac9d8b3..f9ca76129a 100644 --- a/nano/secure/CMakeLists.txt +++ b/nano/secure/CMakeLists.txt @@ -39,12 +39,20 @@ add_library( ${PLATFORM_SECURE_SOURCE} ${CMAKE_BINARY_DIR}/bootstrap_weights_live.cpp ${CMAKE_BINARY_DIR}/bootstrap_weights_beta.cpp + account_info.hpp + account_info.cpp common.hpp common.cpp + generate_cache_flags.hpp + generate_cache_flags.cpp ledger.hpp ledger.cpp + ledger_cache.hpp + ledger_cache.cpp network_filter.hpp network_filter.cpp + pending_info.hpp + pending_info.cpp utility.hpp utility.cpp vote.hpp diff --git a/nano/secure/account_info.cpp b/nano/secure/account_info.cpp new file mode 100644 index 0000000000..b478f95e71 --- /dev/null +++ b/nano/secure/account_info.cpp @@ -0,0 +1,60 @@ +#include + +nano::account_info::account_info (nano::block_hash const & head_a, nano::account const & representative_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, nano::seconds_t modified_a, uint64_t block_count_a, nano::epoch epoch_a) : + head (head_a), + representative (representative_a), + open_block (open_block_a), + balance (balance_a), + modified (modified_a), + block_count (block_count_a), + epoch_m (epoch_a) +{ +} + +bool nano::account_info::deserialize (nano::stream & stream_a) +{ + auto error (false); + try + { + nano::read (stream_a, head.bytes); + nano::read (stream_a, representative.bytes); + nano::read (stream_a, open_block.bytes); + nano::read (stream_a, balance.bytes); + nano::read (stream_a, modified); + nano::read (stream_a, block_count); + nano::read (stream_a, epoch_m); + } + catch (std::runtime_error const &) + { + error = true; + } + + return error; +} + +bool nano::account_info::operator== (nano::account_info const & other_a) const +{ + return head == other_a.head && representative == other_a.representative && open_block == other_a.open_block && balance == other_a.balance && modified == other_a.modified && block_count == other_a.block_count && epoch () == other_a.epoch (); +} + +bool nano::account_info::operator!= (nano::account_info const & other_a) const +{ + return !(*this == other_a); +} + +size_t nano::account_info::db_size () const +{ + debug_assert (reinterpret_cast (this) == reinterpret_cast (&head)); + debug_assert (reinterpret_cast (&head) + sizeof (head) == reinterpret_cast (&representative)); + debug_assert (reinterpret_cast (&representative) + sizeof (representative) == reinterpret_cast (&open_block)); + debug_assert (reinterpret_cast (&open_block) + sizeof (open_block) == reinterpret_cast (&balance)); + debug_assert (reinterpret_cast (&balance) + sizeof (balance) == reinterpret_cast (&modified)); + debug_assert (reinterpret_cast (&modified) + sizeof (modified) == reinterpret_cast (&block_count)); + debug_assert (reinterpret_cast (&block_count) + sizeof (block_count) == reinterpret_cast (&epoch_m)); + return sizeof (head) + sizeof (representative) + sizeof (open_block) + sizeof (balance) + sizeof (modified) + sizeof (block_count) + sizeof (epoch_m); +} + +nano::epoch nano::account_info::epoch () const +{ + return epoch_m; +} diff --git a/nano/secure/account_info.hpp b/nano/secure/account_info.hpp new file mode 100644 index 0000000000..422515fa87 --- /dev/null +++ b/nano/secure/account_info.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +namespace nano +{ +/** + * Latest information about an account + */ +class account_info final +{ +public: + account_info () = default; + account_info (nano::block_hash const &, nano::account const &, nano::block_hash const &, nano::amount const &, nano::seconds_t modified, uint64_t, epoch); + bool deserialize (nano::stream &); + bool operator== (nano::account_info const &) const; + bool operator!= (nano::account_info const &) const; + size_t db_size () const; + nano::epoch epoch () const; + nano::block_hash head{ 0 }; + nano::account representative{}; + nano::block_hash open_block{ 0 }; + nano::amount balance{ 0 }; + /** Seconds since posix epoch */ + nano::seconds_t modified{ 0 }; + uint64_t block_count{ 0 }; + nano::epoch epoch_m{ nano::epoch::epoch_0 }; +}; +} // namespace nano diff --git a/nano/secure/common.cpp b/nano/secure/common.cpp index 35b5ad68f9..d1943ba2cb 100644 --- a/nano/secure/common.cpp +++ b/nano/secure/common.cpp @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include #include @@ -14,12 +16,7 @@ #include #include - -size_t constexpr nano::send_block::size; -size_t constexpr nano::receive_block::size; -size_t constexpr nano::open_block::size; -size_t constexpr nano::change_block::size; -size_t constexpr nano::state_block::size; +#include nano::networks nano::network_constants::active_network = nano::networks::ACTIVE_NETWORK; @@ -27,7 +24,7 @@ namespace { char const * dev_private_key_data = "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4"; char const * dev_public_key_data = "B0311EA55708D6A53C75CDBF88300259C6D018522FE3D4D0A242E431F9E8B6D0"; // xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpiij4txtdo -char const * beta_public_key_data = "259A43ABDB779E97452E188BA3EB951B41C961D3318CA6B925380F4D99F0577A"; // nano_1betagoxpxwykx4kw86dnhosc8t3s7ix8eeentwkcg1hbpez1outjrcyg4n1 +char const * beta_public_key_data = "259A438A8F9F9226130C84D902C237AF3E57C0981C7D709C288046B110D8C8AC"; // nano_1betagoxpxwykx4kw86dnhosc8t3s7ix8eeentwkcg1hbpez1outjrcyg4n1 char const * live_public_key_data = "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA"; // xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3 std::string const test_public_key_data = nano::get_env_or_default ("NANO_TEST_GENESIS_PUB", "45C6FF9D1706D61F0821327752671BDA9F9ED2DA40326B01935AB566FB9E08ED"); // nano_1jg8zygjg3pp5w644emqcbmjqpnzmubfni3kfe1s8pooeuxsw49fdq1mco9j char const * dev_genesis_data = R"%%%({ @@ -41,12 +38,12 @@ char const * dev_genesis_data = R"%%%({ char const * beta_genesis_data = R"%%%({ "type": "open", - "source": "259A43ABDB779E97452E188BA3EB951B41C961D3318CA6B925380F4D99F0577A", - "representative": "nano_1betagoxpxwykx4kw86dnhosc8t3s7ix8eeentwkcg1hbpez1outjrcyg4n1", - "account": "nano_1betagoxpxwykx4kw86dnhosc8t3s7ix8eeentwkcg1hbpez1outjrcyg4n1", - "work": "79d4e27dc873c6f2", - "signature": "4BD7F96F9ED2721BCEE5EAED400EA50AD00524C629AE55E9AFF11220D2C1B00C3D4B3BB770BF67D4F8658023B677F91110193B6C101C2666931F57046A6DB806" - })%%%"; + "source": "259A438A8F9F9226130C84D902C237AF3E57C0981C7D709C288046B110D8C8AC", + "representative": "nano_1betag7az9wk6rbis38s1d35hdsycz1bi95xg4g4j148p6afjk7embcurda4", + "account": "nano_1betag7az9wk6rbis38s1d35hdsycz1bi95xg4g4j148p6afjk7embcurda4", + "work": "e87a3ce39b43b84c", + "signature": "BC588273AC689726D129D3137653FB319B6EE6DB178F97421D11D075B46FD52B6748223C8FF4179399D35CB1A8DF36F759325BD2D3D4504904321FAFB71D7602" + })%%%"; char const * live_genesis_data = R"%%%({ "type": "open", @@ -74,7 +71,7 @@ std::shared_ptr parse_block_from_genesis_data (std::string const & return nano::deserialize_block_json (tree); } -char const * beta_canary_public_key_data = "868C6A9F79D4506E029B378262B91538C5CB26D7C346B63902FFEB365F1C1947"; // nano_33nefchqmo4ifr3bpfw4ecwjcg87semfhit8prwi7zzd8shjr8c9qdxeqmnx +char const * beta_canary_public_key_data = "259a438a8f9f9226130c84d902c237af3e57c0981c7d709c288046b110d8c8ac"; // nano_33nefchqmo4ifr3bpfw4ecwjcg87semfhit8prwi7zzd8shjr8c9qdxeqmnx char const * live_canary_public_key_data = "7CBAF192A3763DAEC9F9BAC1B2CDF665D8369F8400B4BC5AB4BA31C00BAA4404"; // nano_1z7ty8bc8xjxou6zmgp3pd8zesgr8thra17nqjfdbgjjr17tnj16fjntfqfn std::string const test_canary_public_key_data = nano::get_env_or_default ("NANO_TEST_CANARY_PUB", "3BAD2C554ACE05F5E528FBBCE79D51E552C55FA765CCFD89B289C4835DE5F04A"); // nano_1gxf7jcnomi7yqkkjyxwwygo5sckrohtgsgezp6u74g6ifgydw4cajwbk8bf } @@ -130,10 +127,10 @@ nano::ledger_constants::ledger_constants (nano::work_thresholds & work, nano::ne : network_a == nano::networks::nano_test_network ? nano_test_final_votes_canary_height : nano_live_final_votes_canary_height) { - nano_beta_genesis->sideband_set (nano::block_sideband (nano_beta_genesis->account (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); - nano_dev_genesis->sideband_set (nano::block_sideband (nano_dev_genesis->account (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); - nano_live_genesis->sideband_set (nano::block_sideband (nano_live_genesis->account (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); - nano_test_genesis->sideband_set (nano::block_sideband (nano_test_genesis->account (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); + nano_beta_genesis->sideband_set (nano::block_sideband (nano_beta_genesis->account_field ().value (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); + nano_dev_genesis->sideband_set (nano::block_sideband (nano_dev_genesis->account_field ().value (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); + nano_live_genesis->sideband_set (nano::block_sideband (nano_live_genesis->account_field ().value (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); + nano_test_genesis->sideband_set (nano::block_sideband (nano_test_genesis->account_field ().value (), 0, std::numeric_limits::max (), 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0)); nano::link epoch_link_v1; char const * epoch_message_v1 ("epoch v1 block"); @@ -221,131 +218,6 @@ nano::keypair::keypair (std::string const & prv_a) ed25519_publickey (prv.bytes.data (), pub.bytes.data ()); } -nano::account_info::account_info (nano::block_hash const & head_a, nano::account const & representative_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, nano::seconds_t modified_a, uint64_t block_count_a, nano::epoch epoch_a) : - head (head_a), - representative (representative_a), - open_block (open_block_a), - balance (balance_a), - modified (modified_a), - block_count (block_count_a), - epoch_m (epoch_a) -{ -} - -bool nano::account_info::deserialize (nano::stream & stream_a) -{ - auto error (false); - try - { - nano::read (stream_a, head.bytes); - nano::read (stream_a, representative.bytes); - nano::read (stream_a, open_block.bytes); - nano::read (stream_a, balance.bytes); - nano::read (stream_a, modified); - nano::read (stream_a, block_count); - nano::read (stream_a, epoch_m); - } - catch (std::runtime_error const &) - { - error = true; - } - - return error; -} - -bool nano::account_info::operator== (nano::account_info const & other_a) const -{ - return head == other_a.head && representative == other_a.representative && open_block == other_a.open_block && balance == other_a.balance && modified == other_a.modified && block_count == other_a.block_count && epoch () == other_a.epoch (); -} - -bool nano::account_info::operator!= (nano::account_info const & other_a) const -{ - return !(*this == other_a); -} - -size_t nano::account_info::db_size () const -{ - debug_assert (reinterpret_cast (this) == reinterpret_cast (&head)); - debug_assert (reinterpret_cast (&head) + sizeof (head) == reinterpret_cast (&representative)); - debug_assert (reinterpret_cast (&representative) + sizeof (representative) == reinterpret_cast (&open_block)); - debug_assert (reinterpret_cast (&open_block) + sizeof (open_block) == reinterpret_cast (&balance)); - debug_assert (reinterpret_cast (&balance) + sizeof (balance) == reinterpret_cast (&modified)); - debug_assert (reinterpret_cast (&modified) + sizeof (modified) == reinterpret_cast (&block_count)); - debug_assert (reinterpret_cast (&block_count) + sizeof (block_count) == reinterpret_cast (&epoch_m)); - return sizeof (head) + sizeof (representative) + sizeof (open_block) + sizeof (balance) + sizeof (modified) + sizeof (block_count) + sizeof (epoch_m); -} - -nano::epoch nano::account_info::epoch () const -{ - return epoch_m; -} - -nano::pending_info::pending_info (nano::account const & source_a, nano::amount const & amount_a, nano::epoch epoch_a) : - source (source_a), - amount (amount_a), - epoch (epoch_a) -{ -} - -bool nano::pending_info::deserialize (nano::stream & stream_a) -{ - auto error (false); - try - { - nano::read (stream_a, source.bytes); - nano::read (stream_a, amount.bytes); - nano::read (stream_a, epoch); - } - catch (std::runtime_error const &) - { - error = true; - } - - return error; -} - -size_t nano::pending_info::db_size () const -{ - return sizeof (source) + sizeof (amount) + sizeof (epoch); -} - -bool nano::pending_info::operator== (nano::pending_info const & other_a) const -{ - return source == other_a.source && amount == other_a.amount && epoch == other_a.epoch; -} - -nano::pending_key::pending_key (nano::account const & account_a, nano::block_hash const & hash_a) : - account (account_a), - hash (hash_a) -{ -} - -bool nano::pending_key::deserialize (nano::stream & stream_a) -{ - auto error (false); - try - { - nano::read (stream_a, account.bytes); - nano::read (stream_a, hash.bytes); - } - catch (std::runtime_error const &) - { - error = true; - } - - return error; -} - -bool nano::pending_key::operator== (nano::pending_key const & other_a) const -{ - return account == other_a.account && hash == other_a.hash; -} - -nano::account const & nano::pending_key::key () const -{ - return account; -} - nano::unchecked_info::unchecked_info (std::shared_ptr const & block_a) : block (block_a), modified_m (nano::seconds_since_epoch ()) @@ -487,47 +359,14 @@ nano::block_hash const & nano::unchecked_key::key () const return previous; } -void nano::generate_cache::enable_all () +std::string_view nano::to_string (nano::block_status code) { - reps = true; - cemented_count = true; - unchecked_count = true; - account_count = true; + return magic_enum::enum_name (code); } -nano::stat::detail nano::to_stat_detail (nano::process_result process_result) +nano::stat::detail nano::to_stat_detail (nano::block_status code) { - switch (process_result) - { - case process_result::progress: - return nano::stat::detail::progress; - case process_result::bad_signature: - return nano::stat::detail::bad_signature; - case process_result::old: - return nano::stat::detail::old; - case process_result::negative_spend: - return nano::stat::detail::negative_spend; - case process_result::fork: - return nano::stat::detail::fork; - case process_result::unreceivable: - return nano::stat::detail::unreceivable; - case process_result::gap_previous: - return nano::stat::detail::gap_previous; - case process_result::gap_source: - return nano::stat::detail::gap_source; - case process_result::gap_epoch_open_pending: - return nano::stat::detail::gap_epoch_open_pending; - case process_result::opened_burn_account: - return nano::stat::detail::opened_burn_account; - case process_result::balance_mismatch: - return nano::stat::detail::balance_mismatch; - case process_result::representative_mismatch: - return nano::stat::detail::representative_mismatch; - case process_result::block_position: - return nano::stat::detail::block_position; - case process_result::insufficient_work: - return nano::stat::detail::insufficient_work; - } - debug_assert (false && "There should be always a defined nano::stat::detail that is not _last"); - return nano::stat::detail::_last; + auto value = magic_enum::enum_cast (magic_enum::enum_name (code)); + debug_assert (value); + return value.value_or (nano::stat::detail{}); } diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index b14323edf5..e1d43fec89 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -2,10 +2,10 @@ #include #include -#include #include #include #include +#include #include #include #include @@ -98,56 +98,6 @@ class keypair nano::raw_key prv; }; -/** - * Latest information about an account - */ -class account_info final -{ -public: - account_info () = default; - account_info (nano::block_hash const &, nano::account const &, nano::block_hash const &, nano::amount const &, nano::seconds_t modified, uint64_t, epoch); - bool deserialize (nano::stream &); - bool operator== (nano::account_info const &) const; - bool operator!= (nano::account_info const &) const; - size_t db_size () const; - nano::epoch epoch () const; - nano::block_hash head{ 0 }; - nano::account representative{}; - nano::block_hash open_block{ 0 }; - nano::amount balance{ 0 }; - /** Seconds since posix epoch */ - nano::seconds_t modified{ 0 }; - uint64_t block_count{ 0 }; - nano::epoch epoch_m{ nano::epoch::epoch_0 }; -}; - -/** - * Information on an uncollected send - */ -class pending_info final -{ -public: - pending_info () = default; - pending_info (nano::account const &, nano::amount const &, nano::epoch); - size_t db_size () const; - bool deserialize (nano::stream &); - bool operator== (nano::pending_info const &) const; - nano::account source{}; - nano::amount amount{ 0 }; - nano::epoch epoch{ nano::epoch::epoch_0 }; -}; -class pending_key final -{ -public: - pending_key () = default; - pending_key (nano::account const &, nano::block_hash const &); - bool deserialize (nano::stream &); - bool operator== (nano::pending_key const &) const; - nano::account const & key () const; - nano::account account{}; - nano::block_hash hash{ 0 }; -}; - class endpoint_key final { public: @@ -252,7 +202,7 @@ enum class vote_code indeterminate // Unknown if replay or vote }; -enum class process_result +enum class block_status { progress, // Hasn't been seen before, signed correctly bad_signature, // Signature was bad, forged or transmission error @@ -269,11 +219,10 @@ enum class process_result block_position, // This block cannot follow the previous block insufficient_work // Insufficient work for this block, even though it passed the minimal validation }; -class process_return final -{ -public: - nano::process_result code; -}; + +std::string_view to_string (block_status); +nano::stat::detail to_stat_detail (block_status); + enum class tally_result { vote, @@ -281,8 +230,6 @@ enum class tally_result confirm }; -nano::stat::detail to_stat_detail (process_result); - class network_params; /** Genesis keys and ledger constants for network variants */ @@ -408,32 +355,6 @@ enum class confirmation_height_mode bounded }; -/* Holds flags for various cacheable data. For most CLI operations caching is unnecessary - * (e.g getting the cemented block count) so it can be disabled for performance reasons. */ -class generate_cache -{ -public: - bool reps = true; - bool cemented_count = true; - bool unchecked_count = true; - bool account_count = true; - bool block_count = true; - - void enable_all (); -}; - -/* Holds an in-memory cache of various counts */ -class ledger_cache -{ -public: - nano::rep_weights rep_weights; - std::atomic cemented_count{ 0 }; - std::atomic block_count{ 0 }; - std::atomic pruned_count{ 0 }; - std::atomic account_count{ 0 }; - std::atomic final_votes_confirmation_canary{ false }; -}; - /* Defines the possible states for an election to stop in */ enum class election_status_type : uint8_t { diff --git a/nano/secure/generate_cache_flags.cpp b/nano/secure/generate_cache_flags.cpp new file mode 100644 index 0000000000..912932ceed --- /dev/null +++ b/nano/secure/generate_cache_flags.cpp @@ -0,0 +1,9 @@ +#include + +void nano::generate_cache_flags::enable_all () +{ + reps = true; + cemented_count = true; + unchecked_count = true; + account_count = true; +} diff --git a/nano/secure/generate_cache_flags.hpp b/nano/secure/generate_cache_flags.hpp new file mode 100644 index 0000000000..29445e53d8 --- /dev/null +++ b/nano/secure/generate_cache_flags.hpp @@ -0,0 +1,18 @@ +#pragma once + +namespace nano +{ +/* Holds flags for various cacheable data. For most CLI operations caching is unnecessary + * (e.g getting the cemented block count) so it can be disabled for performance reasons. */ +class generate_cache_flags +{ +public: + bool reps = true; + bool cemented_count = true; + bool unchecked_count = true; + bool account_count = true; + bool block_count = true; + + void enable_all (); +}; +} diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index e7c7f1abf9..8e69bde8ef 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -37,23 +39,24 @@ class rollback_visitor : public nano::block_visitor void send_block (nano::send_block const & block_a) override { auto hash (block_a.hash ()); - nano::pending_info pending; nano::pending_key key (block_a.hashables.destination, hash); - while (!error && ledger.store.pending.get (transaction, key, pending)) + auto pending = ledger.store.pending.get (transaction, key); + while (!error && !pending.has_value ()) { error = ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.destination), list); + pending = ledger.store.pending.get (transaction, key); } if (!error) { - auto info = ledger.account_info (transaction, pending.source); + auto info = ledger.account_info (transaction, pending.value ().source); debug_assert (info); ledger.store.pending.del (transaction, key); - ledger.cache.rep_weights.representation_add (info->representative, pending.amount.number ()); - nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); - ledger.update_account (transaction, pending.source, *info, new_info); + ledger.cache.rep_weights.representation_add (info->representative, pending.value ().amount.number ()); + nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous).value (), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); + ledger.update_account (transaction, pending.value ().source, *info, new_info); ledger.store.block.del (transaction, hash); ledger.store.frontier.del (transaction, hash); - ledger.store.frontier.put (transaction, block_a.hashables.previous, pending.source); + ledger.store.frontier.put (transaction, block_a.hashables.previous, pending.value ().source); ledger.store.block.successor_clear (transaction, block_a.hashables.previous); ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::send); } @@ -61,18 +64,17 @@ class rollback_visitor : public nano::block_visitor void receive_block (nano::receive_block const & block_a) override { auto hash (block_a.hash ()); - auto amount (ledger.amount (transaction, hash)); - auto destination_account (ledger.account (transaction, hash)); + auto amount = ledger.amount (transaction, hash).value (); + auto destination_account = block_a.account (); // Pending account entry can be incorrect if source block was pruned. But it's not affecting correct ledger processing - [[maybe_unused]] bool is_pruned (false); - auto source_account (ledger.account_safe (transaction, block_a.hashables.source, is_pruned)); + auto source_account = ledger.account (transaction, block_a.hashables.source); auto info = ledger.account_info (transaction, destination_account); debug_assert (info); ledger.cache.rep_weights.representation_add (info->representative, 0 - amount); - nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); + nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous).value (), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); ledger.update_account (transaction, destination_account, *info, new_info); ledger.store.block.del (transaction, hash); - ledger.store.pending.put (transaction, nano::pending_key (destination_account, block_a.hashables.source), { source_account, amount, nano::epoch::epoch_0 }); + ledger.store.pending.put (transaction, nano::pending_key (destination_account, block_a.hashables.source), { source_account.value_or (0), amount, nano::epoch::epoch_0 }); ledger.store.frontier.del (transaction, hash); ledger.store.frontier.put (transaction, block_a.hashables.previous, destination_account); ledger.store.block.successor_clear (transaction, block_a.hashables.previous); @@ -81,16 +83,14 @@ class rollback_visitor : public nano::block_visitor void open_block (nano::open_block const & block_a) override { auto hash (block_a.hash ()); - auto amount (ledger.amount (transaction, hash)); - auto destination_account (ledger.account (transaction, hash)); - // Pending account entry can be incorrect if source block was pruned. But it's not affecting correct ledger processing - [[maybe_unused]] bool is_pruned (false); - auto source_account (ledger.account_safe (transaction, block_a.hashables.source, is_pruned)); - ledger.cache.rep_weights.representation_add (block_a.representative (), 0 - amount); + auto amount = ledger.amount (transaction, hash).value (); + auto destination_account = block_a.account (); + auto source_account = ledger.account (transaction, block_a.hashables.source); + ledger.cache.rep_weights.representation_add (block_a.representative_field ().value (), 0 - amount); nano::account_info new_info; ledger.update_account (transaction, destination_account, new_info, new_info); ledger.store.block.del (transaction, hash); - ledger.store.pending.put (transaction, nano::pending_key (destination_account, block_a.hashables.source), { source_account, amount, nano::epoch::epoch_0 }); + ledger.store.pending.put (transaction, nano::pending_key (destination_account, block_a.hashables.source), { source_account.value_or (0), amount, nano::epoch::epoch_0 }); ledger.store.frontier.del (transaction, hash); ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::open); } @@ -98,14 +98,14 @@ class rollback_visitor : public nano::block_visitor { auto hash (block_a.hash ()); auto rep_block (ledger.representative (transaction, block_a.hashables.previous)); - auto account (ledger.account (transaction, block_a.hashables.previous)); + auto account = block_a.account (); auto info = ledger.account_info (transaction, account); debug_assert (info); - auto balance (ledger.balance (transaction, block_a.hashables.previous)); + auto balance = ledger.balance (transaction, block_a.hashables.previous).value (); auto block = ledger.store.block.get (transaction, rep_block); release_assert (block != nullptr); - auto representative = block->representative (); - ledger.cache.rep_weights.representation_add_dual (block_a.representative (), 0 - balance, representative, balance); + auto representative = block->representative_field ().value (); + ledger.cache.rep_weights.representation_add_dual (block_a.hashables.representative, 0 - balance, representative, balance); ledger.store.block.del (transaction, hash); nano::account_info new_info (block_a.hashables.previous, representative, info->open_block, info->balance, nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); @@ -122,7 +122,7 @@ class rollback_visitor : public nano::block_visitor { rep_block_hash = ledger.representative (transaction, block_a.hashables.previous); } - auto balance (ledger.balance (transaction, block_a.hashables.previous)); + nano::uint128_t balance = ledger.balance (transaction, block_a.hashables.previous).value_or (0); auto is_send (block_a.hashables.balance < balance); nano::account representative{}; if (!rep_block_hash.is_zero ()) @@ -130,13 +130,13 @@ class rollback_visitor : public nano::block_visitor // Move existing representation & add in amount delta auto block (ledger.store.block.get (transaction, rep_block_hash)); debug_assert (block != nullptr); - representative = block->representative (); - ledger.cache.rep_weights.representation_add_dual (representative, balance, block_a.representative (), 0 - block_a.hashables.balance.number ()); + representative = block->representative_field ().value (); + ledger.cache.rep_weights.representation_add_dual (representative, balance, block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); } else { // Add in amount delta only - ledger.cache.rep_weights.representation_add (block_a.representative (), 0 - block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add (block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); } auto info = ledger.account_info (transaction, block_a.hashables.account); @@ -155,9 +155,8 @@ class rollback_visitor : public nano::block_visitor else if (!block_a.hashables.link.is_zero () && !ledger.is_epoch_link (block_a.hashables.link)) { // Pending account entry can be incorrect if source block was pruned. But it's not affecting correct ledger processing - [[maybe_unused]] bool is_pruned (false); - auto source_account (ledger.account_safe (transaction, block_a.hashables.link.as_block_hash (), is_pruned)); - nano::pending_info pending_info (source_account, block_a.hashables.balance.number () - balance, block_a.sideband ().source_epoch); + auto source_account = ledger.account (transaction, block_a.hashables.link.as_block_hash ()); + nano::pending_info pending_info (source_account.value_or (0), block_a.hashables.balance.number () - balance, block_a.sideband ().source_epoch); ledger.store.pending.put (transaction, nano::pending_key (block_a.hashables.account, block_a.hashables.link.as_block_hash ()), pending_info); ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::receive); } @@ -202,7 +201,7 @@ class ledger_processor : public nano::mutable_block_visitor void epoch_block_impl (nano::state_block &); nano::ledger & ledger; nano::store::write_transaction const & transaction; - nano::process_return result; + nano::block_status result; private: bool validate_epoch_block (nano::state_block const & block_a); @@ -215,10 +214,10 @@ bool ledger_processor::validate_epoch_block (nano::state_block const & block_a) nano::amount prev_balance (0); if (!block_a.hashables.previous.is_zero ()) { - result.code = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::process_result::progress : nano::process_result::gap_previous; - if (result.code == nano::process_result::progress) + result = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::block_status::progress : nano::block_status::gap_previous; + if (result == nano::block_status::progress) { - prev_balance = ledger.balance (transaction, block_a.hashables.previous); + prev_balance = ledger.balance (transaction, block_a.hashables.previous).value (); } else { @@ -226,9 +225,9 @@ bool ledger_processor::validate_epoch_block (nano::state_block const & block_a) if (validate_message (block_a.hashables.account, block_a.hash (), block_a.signature)) { // Is epoch block signed correctly - if (validate_message (ledger.epoch_signer (block_a.link ()), block_a.hash (), block_a.signature)) + if (validate_message (ledger.epoch_signer (block_a.link_field ().value ()), block_a.hash (), block_a.signature)) { - result.code = nano::process_result::bad_signature; + result = nano::block_status::bad_signature; } } } @@ -238,7 +237,7 @@ bool ledger_processor::validate_epoch_block (nano::state_block const & block_a) void ledger_processor::state_block (nano::state_block & block_a) { - result.code = nano::process_result::progress; + result = nano::block_status::progress; auto is_epoch_block = false; if (ledger.is_epoch_link (block_a.hashables.link)) { @@ -246,7 +245,7 @@ void ledger_processor::state_block (nano::state_block & block_a) is_epoch_block = validate_epoch_block (block_a); } - if (result.code == nano::process_result::progress) + if (result == nano::block_status::progress) { if (is_epoch_block) { @@ -263,15 +262,15 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block before? (Unambiguous) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block before? (Unambiguous) + if (result == nano::block_status::progress) { - result.code = validate_message (block_a.hashables.account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Unambiguous) - if (result.code == nano::process_result::progress) + result = validate_message (block_a.hashables.account, hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is this block signed correctly (Unambiguous) + if (result == nano::block_status::progress) { debug_assert (!validate_message (block_a.hashables.account, hash, block_a.signature)); - result.code = block_a.hashables.account.is_zero () ? nano::process_result::opened_burn_account : nano::process_result::progress; // Is this for the burn account? (Unambiguous) - if (result.code == nano::process_result::progress) + result = block_a.hashables.account.is_zero () ? nano::block_status::opened_burn_account : nano::block_status::progress; // Is this for the burn account? (Unambiguous) + if (result == nano::block_status::progress) { nano::epoch epoch (nano::epoch::epoch_0); nano::epoch source_epoch (nano::epoch::epoch_0); @@ -284,45 +283,45 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) { // Account already exists epoch = info.epoch (); - result.code = block_a.hashables.previous.is_zero () ? nano::process_result::fork : nano::process_result::progress; // Has this account already been opened? (Ambigious) - if (result.code == nano::process_result::progress) + result = block_a.hashables.previous.is_zero () ? nano::block_status::fork : nano::block_status::progress; // Has this account already been opened? (Ambigious) + if (result == nano::block_status::progress) { - result.code = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::process_result::progress : nano::process_result::gap_previous; // Does the previous block exist in the ledger? (Unambigious) - if (result.code == nano::process_result::progress) + result = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::block_status::progress : nano::block_status::gap_previous; // Does the previous block exist in the ledger? (Unambigious) + if (result == nano::block_status::progress) { is_send = block_a.hashables.balance < info.balance; is_receive = !is_send && !block_a.hashables.link.is_zero (); amount = is_send ? (info.balance.number () - amount.number ()) : (amount.number () - info.balance.number ()); - result.code = block_a.hashables.previous == info.head ? nano::process_result::progress : nano::process_result::fork; // Is the previous block the account's head block? (Ambigious) + result = block_a.hashables.previous == info.head ? nano::block_status::progress : nano::block_status::fork; // Is the previous block the account's head block? (Ambigious) } } } else { // Account does not yet exists - result.code = block_a.previous ().is_zero () ? nano::process_result::progress : nano::process_result::gap_previous; // Does the first block in an account yield 0 for previous() ? (Unambigious) - if (result.code == nano::process_result::progress) + result = block_a.previous ().is_zero () ? nano::block_status::progress : nano::block_status::gap_previous; // Does the first block in an account yield 0 for previous() ? (Unambigious) + if (result == nano::block_status::progress) { is_receive = true; - result.code = !block_a.hashables.link.is_zero () ? nano::process_result::progress : nano::process_result::gap_source; // Is the first block receiving from a send ? (Unambigious) + result = !block_a.hashables.link.is_zero () ? nano::block_status::progress : nano::block_status::gap_source; // Is the first block receiving from a send ? (Unambigious) } } - if (result.code == nano::process_result::progress) + if (result == nano::block_status::progress) { if (!is_send) { if (!block_a.hashables.link.is_zero ()) { - result.code = ledger.block_or_pruned_exists (transaction, block_a.hashables.link.as_block_hash ()) ? nano::process_result::progress : nano::process_result::gap_source; // Have we seen the source block already? (Harmless) - if (result.code == nano::process_result::progress) + result = ledger.block_or_pruned_exists (transaction, block_a.hashables.link.as_block_hash ()) ? nano::block_status::progress : nano::block_status::gap_source; // Have we seen the source block already? (Harmless) + if (result == nano::block_status::progress) { nano::pending_key key (block_a.hashables.account, block_a.hashables.link.as_block_hash ()); - nano::pending_info pending; - result.code = ledger.store.pending.get (transaction, key, pending) ? nano::process_result::unreceivable : nano::process_result::progress; // Has this source already been received (Malformed) - if (result.code == nano::process_result::progress) + auto pending = ledger.store.pending.get (transaction, key); + result = !pending ? nano::block_status::unreceivable : nano::block_status::progress; // Has this source already been received (Malformed) + if (result == nano::block_status::progress) { - result.code = amount == pending.amount ? nano::process_result::progress : nano::process_result::balance_mismatch; - source_epoch = pending.epoch; + result = amount == pending.value ().amount ? nano::block_status::progress : nano::block_status::balance_mismatch; + source_epoch = pending.value ().epoch; epoch = std::max (epoch, source_epoch); } } @@ -330,15 +329,15 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) else { // If there's no link, the balance must remain the same, only the representative can change - result.code = amount.is_zero () ? nano::process_result::progress : nano::process_result::balance_mismatch; + result = amount.is_zero () ? nano::block_status::progress : nano::block_status::balance_mismatch; } } } - if (result.code == nano::process_result::progress) + if (result == nano::block_status::progress) { nano::block_details block_details (epoch, is_send, is_receive, false); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block); block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details, source_epoch)); @@ -347,12 +346,12 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) if (!info.head.is_zero ()) { // Move existing representation & add in amount delta - ledger.cache.rep_weights.representation_add_dual (info.representative, 0 - info.balance.number (), block_a.representative (), block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add_dual (info.representative, 0 - info.balance.number (), block_a.hashables.representative, block_a.hashables.balance.number ()); } else { // Add in amount delta only - ledger.cache.rep_weights.representation_add (block_a.representative (), block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add (block_a.hashables.representative, block_a.hashables.balance.number ()); } if (is_send) @@ -366,7 +365,7 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) ledger.store.pending.del (transaction, nano::pending_key (block_a.hashables.account, block_a.hashables.link.as_block_hash ())); } - nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch); + nano::account_info new_info (hash, block_a.hashables.representative, info.open_block.is_zero () ? hash : info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch); ledger.update_account (transaction, block_a.hashables.account, info, new_info); if (!ledger.store.frontier.get (transaction, info.head).is_zero ()) { @@ -383,60 +382,60 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block before? (Unambiguous) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block before? (Unambiguous) + if (result == nano::block_status::progress) { - result.code = validate_message (ledger.epoch_signer (block_a.hashables.link), hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Unambiguous) - if (result.code == nano::process_result::progress) + result = validate_message (ledger.epoch_signer (block_a.hashables.link), hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is this block signed correctly (Unambiguous) + if (result == nano::block_status::progress) { debug_assert (!validate_message (ledger.epoch_signer (block_a.hashables.link), hash, block_a.signature)); - result.code = block_a.hashables.account.is_zero () ? nano::process_result::opened_burn_account : nano::process_result::progress; // Is this for the burn account? (Unambiguous) - if (result.code == nano::process_result::progress) + result = block_a.hashables.account.is_zero () ? nano::block_status::opened_burn_account : nano::block_status::progress; // Is this for the burn account? (Unambiguous) + if (result == nano::block_status::progress) { nano::account_info info; auto account_error (ledger.store.account.get (transaction, block_a.hashables.account, info)); if (!account_error) { // Account already exists - result.code = block_a.hashables.previous.is_zero () ? nano::process_result::fork : nano::process_result::progress; // Has this account already been opened? (Ambigious) - if (result.code == nano::process_result::progress) + result = block_a.hashables.previous.is_zero () ? nano::block_status::fork : nano::block_status::progress; // Has this account already been opened? (Ambigious) + if (result == nano::block_status::progress) { - result.code = block_a.hashables.previous == info.head ? nano::process_result::progress : nano::process_result::fork; // Is the previous block the account's head block? (Ambigious) - if (result.code == nano::process_result::progress) + result = block_a.hashables.previous == info.head ? nano::block_status::progress : nano::block_status::fork; // Is the previous block the account's head block? (Ambigious) + if (result == nano::block_status::progress) { - result.code = block_a.hashables.representative == info.representative ? nano::process_result::progress : nano::process_result::representative_mismatch; + result = block_a.hashables.representative == info.representative ? nano::block_status::progress : nano::block_status::representative_mismatch; } } } else { - result.code = block_a.hashables.representative.is_zero () ? nano::process_result::progress : nano::process_result::representative_mismatch; + result = block_a.hashables.representative.is_zero () ? nano::block_status::progress : nano::block_status::representative_mismatch; // Non-exisitng account should have pending entries - if (result.code == nano::process_result::progress) + if (result == nano::block_status::progress) { bool pending_exists = ledger.store.pending.any (transaction, block_a.hashables.account); - result.code = pending_exists ? nano::process_result::progress : nano::process_result::gap_epoch_open_pending; + result = pending_exists ? nano::block_status::progress : nano::block_status::gap_epoch_open_pending; } } - if (result.code == nano::process_result::progress) + if (result == nano::block_status::progress) { auto epoch = ledger.constants.epochs.epoch (block_a.hashables.link); // Must be an epoch for an unopened account or the epoch upgrade must be sequential auto is_valid_epoch_upgrade = account_error ? static_cast> (epoch) > 0 : nano::epochs::is_sequential (info.epoch (), epoch); - result.code = is_valid_epoch_upgrade ? nano::process_result::progress : nano::process_result::block_position; - if (result.code == nano::process_result::progress) + result = is_valid_epoch_upgrade ? nano::block_status::progress : nano::block_status::block_position; + if (result == nano::block_status::progress) { - result.code = block_a.hashables.balance == info.balance ? nano::process_result::progress : nano::process_result::balance_mismatch; - if (result.code == nano::process_result::progress) + result = block_a.hashables.balance == info.balance ? nano::block_status::progress : nano::block_status::balance_mismatch; + if (result == nano::block_status::progress) { nano::block_details block_details (epoch, false, false, true); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block); block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); ledger.store.block.put (transaction, hash, block_a); - nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch); + nano::account_info new_info (hash, block_a.hashables.representative, info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch); ledger.update_account (transaction, block_a.hashables.account, info, new_info); if (!ledger.store.frontier.get (transaction, info.head).is_zero ()) { @@ -455,36 +454,36 @@ void ledger_processor::change_block (nano::change_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block before? (Harmless) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block before? (Harmless) + if (result == nano::block_status::progress) { auto previous (ledger.store.block.get (transaction, block_a.hashables.previous)); - result.code = previous != nullptr ? nano::process_result::progress : nano::process_result::gap_previous; // Have we seen the previous block already? (Harmless) - if (result.code == nano::process_result::progress) + result = previous != nullptr ? nano::block_status::progress : nano::block_status::gap_previous; // Have we seen the previous block already? (Harmless) + if (result == nano::block_status::progress) { - result.code = block_a.valid_predecessor (*previous) ? nano::process_result::progress : nano::process_result::block_position; - if (result.code == nano::process_result::progress) + result = block_a.valid_predecessor (*previous) ? nano::block_status::progress : nano::block_status::block_position; + if (result == nano::block_status::progress) { auto account (ledger.store.frontier.get (transaction, block_a.hashables.previous)); - result.code = account.is_zero () ? nano::process_result::fork : nano::process_result::progress; - if (result.code == nano::process_result::progress) + result = account.is_zero () ? nano::block_status::fork : nano::block_status::progress; + if (result == nano::block_status::progress) { auto info = ledger.account_info (transaction, account); debug_assert (info); debug_assert (info->head == block_a.hashables.previous); - result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed) - if (result.code == nano::process_result::progress) + result = validate_message (account, hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is this block signed correctly (Malformed) + if (result == nano::block_status::progress) { nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { debug_assert (!validate_message (account, hash, block_a.signature)); block_a.sideband_set (nano::block_sideband (account, 0, info->balance, info->block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); ledger.store.block.put (transaction, hash, block_a); - auto balance (ledger.balance (transaction, block_a.hashables.previous)); - ledger.cache.rep_weights.representation_add_dual (block_a.representative (), balance, info->representative, 0 - balance); - nano::account_info new_info (hash, block_a.representative (), info->open_block, info->balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); + auto balance = previous->balance (); + ledger.cache.rep_weights.representation_add_dual (block_a.hashables.representative, balance.number (), info->representative, 0 - balance.number ()); + nano::account_info new_info (hash, block_a.hashables.representative, info->open_block, info->balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); ledger.store.frontier.del (transaction, block_a.hashables.previous); ledger.store.frontier.put (transaction, hash, account); @@ -501,33 +500,33 @@ void ledger_processor::send_block (nano::send_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block before? (Harmless) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block before? (Harmless) + if (result == nano::block_status::progress) { auto previous (ledger.store.block.get (transaction, block_a.hashables.previous)); - result.code = previous != nullptr ? nano::process_result::progress : nano::process_result::gap_previous; // Have we seen the previous block already? (Harmless) - if (result.code == nano::process_result::progress) + result = previous != nullptr ? nano::block_status::progress : nano::block_status::gap_previous; // Have we seen the previous block already? (Harmless) + if (result == nano::block_status::progress) { - result.code = block_a.valid_predecessor (*previous) ? nano::process_result::progress : nano::process_result::block_position; - if (result.code == nano::process_result::progress) + result = block_a.valid_predecessor (*previous) ? nano::block_status::progress : nano::block_status::block_position; + if (result == nano::block_status::progress) { auto account (ledger.store.frontier.get (transaction, block_a.hashables.previous)); - result.code = account.is_zero () ? nano::process_result::fork : nano::process_result::progress; - if (result.code == nano::process_result::progress) + result = account.is_zero () ? nano::block_status::fork : nano::block_status::progress; + if (result == nano::block_status::progress) { - result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed) - if (result.code == nano::process_result::progress) + result = validate_message (account, hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is this block signed correctly (Malformed) + if (result == nano::block_status::progress) { nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { debug_assert (!validate_message (account, hash, block_a.signature)); auto info = ledger.account_info (transaction, account); debug_assert (info); debug_assert (info->head == block_a.hashables.previous); - result.code = info->balance.number () >= block_a.hashables.balance.number () ? nano::process_result::progress : nano::process_result::negative_spend; // Is this trying to spend a negative amount (Malicious) - if (result.code == nano::process_result::progress) + result = info->balance.number () >= block_a.hashables.balance.number () ? nano::block_status::progress : nano::block_status::negative_spend; // Is this trying to spend a negative amount (Malicious) + if (result == nano::block_status::progress) { auto amount (info->balance.number () - block_a.hashables.balance.number ()); ledger.cache.rep_weights.representation_add (info->representative, 0 - amount); @@ -552,49 +551,49 @@ void ledger_processor::receive_block (nano::receive_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block already? (Harmless) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block already? (Harmless) + if (result == nano::block_status::progress) { auto previous (ledger.store.block.get (transaction, block_a.hashables.previous)); - result.code = previous != nullptr ? nano::process_result::progress : nano::process_result::gap_previous; - if (result.code == nano::process_result::progress) + result = previous != nullptr ? nano::block_status::progress : nano::block_status::gap_previous; + if (result == nano::block_status::progress) { - result.code = block_a.valid_predecessor (*previous) ? nano::process_result::progress : nano::process_result::block_position; - if (result.code == nano::process_result::progress) + result = block_a.valid_predecessor (*previous) ? nano::block_status::progress : nano::block_status::block_position; + if (result == nano::block_status::progress) { auto account (ledger.store.frontier.get (transaction, block_a.hashables.previous)); - result.code = account.is_zero () ? nano::process_result::gap_previous : nano::process_result::progress; // Have we seen the previous block? No entries for account at all (Harmless) - if (result.code == nano::process_result::progress) + result = account.is_zero () ? nano::block_status::gap_previous : nano::block_status::progress; // Have we seen the previous block? No entries for account at all (Harmless) + if (result == nano::block_status::progress) { - result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is the signature valid (Malformed) - if (result.code == nano::process_result::progress) + result = validate_message (account, hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is the signature valid (Malformed) + if (result == nano::block_status::progress) { debug_assert (!validate_message (account, hash, block_a.signature)); - result.code = ledger.block_or_pruned_exists (transaction, block_a.hashables.source) ? nano::process_result::progress : nano::process_result::gap_source; // Have we seen the source block already? (Harmless) - if (result.code == nano::process_result::progress) + result = ledger.block_or_pruned_exists (transaction, block_a.hashables.source) ? nano::block_status::progress : nano::block_status::gap_source; // Have we seen the source block already? (Harmless) + if (result == nano::block_status::progress) { auto info = ledger.account_info (transaction, account); debug_assert (info); - result.code = info->head == block_a.hashables.previous ? nano::process_result::progress : nano::process_result::gap_previous; // Block doesn't immediately follow latest block (Harmless) - if (result.code == nano::process_result::progress) + result = info->head == block_a.hashables.previous ? nano::block_status::progress : nano::block_status::gap_previous; // Block doesn't immediately follow latest block (Harmless) + if (result == nano::block_status::progress) { nano::pending_key key (account, block_a.hashables.source); - nano::pending_info pending; - result.code = ledger.store.pending.get (transaction, key, pending) ? nano::process_result::unreceivable : nano::process_result::progress; // Has this source already been received (Malformed) - if (result.code == nano::process_result::progress) + auto pending = ledger.store.pending.get (transaction, key); + result = !pending ? nano::block_status::unreceivable : nano::block_status::progress; // Has this source already been received (Malformed) + if (result == nano::block_status::progress) { - result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed) - if (result.code == nano::process_result::progress) + result = pending.value ().epoch == nano::epoch::epoch_0 ? nano::block_status::progress : nano::block_status::unreceivable; // Are we receiving a state-only send? (Malformed) + if (result == nano::block_status::progress) { nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { - auto new_balance (info->balance.number () + pending.amount.number ()); + auto new_balance (info->balance.number () + pending.value ().amount.number ()); #ifdef NDEBUG if (ledger.store.block.exists (transaction, block_a.hashables.source)) { - auto info = ledger.account_info (transaction, pending.source); + auto info = ledger.account_info (transaction, pending.value ().source); debug_assert (info); } #endif @@ -603,7 +602,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a) ledger.store.block.put (transaction, hash, block_a); nano::account_info new_info (hash, info->representative, info->open_block, new_balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); - ledger.cache.rep_weights.representation_add (info->representative, pending.amount.number ()); + ledger.cache.rep_weights.representation_add (info->representative, pending.value ().amount.number ()); ledger.store.frontier.del (transaction, block_a.hashables.previous); ledger.store.frontier.put (transaction, hash, account); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::receive); @@ -616,7 +615,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a) } else { - result.code = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::process_result::fork : nano::process_result::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious) + result = ledger.store.block.exists (transaction, block_a.hashables.previous) ? nano::block_status::fork : nano::block_status::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious) } } } @@ -627,49 +626,49 @@ void ledger_processor::open_block (nano::open_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.block_or_pruned_exists (transaction, hash)); - result.code = existing ? nano::process_result::old : nano::process_result::progress; // Have we seen this block already? (Harmless) - if (result.code == nano::process_result::progress) + result = existing ? nano::block_status::old : nano::block_status::progress; // Have we seen this block already? (Harmless) + if (result == nano::block_status::progress) { - result.code = validate_message (block_a.hashables.account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is the signature valid (Malformed) - if (result.code == nano::process_result::progress) + result = validate_message (block_a.hashables.account, hash, block_a.signature) ? nano::block_status::bad_signature : nano::block_status::progress; // Is the signature valid (Malformed) + if (result == nano::block_status::progress) { debug_assert (!validate_message (block_a.hashables.account, hash, block_a.signature)); - result.code = ledger.block_or_pruned_exists (transaction, block_a.hashables.source) ? nano::process_result::progress : nano::process_result::gap_source; // Have we seen the source block? (Harmless) - if (result.code == nano::process_result::progress) + result = ledger.block_or_pruned_exists (transaction, block_a.hashables.source) ? nano::block_status::progress : nano::block_status::gap_source; // Have we seen the source block? (Harmless) + if (result == nano::block_status::progress) { nano::account_info info; - result.code = ledger.store.account.get (transaction, block_a.hashables.account, info) ? nano::process_result::progress : nano::process_result::fork; // Has this account already been opened? (Malicious) - if (result.code == nano::process_result::progress) + result = ledger.store.account.get (transaction, block_a.hashables.account, info) ? nano::block_status::progress : nano::block_status::fork; // Has this account already been opened? (Malicious) + if (result == nano::block_status::progress) { nano::pending_key key (block_a.hashables.account, block_a.hashables.source); - nano::pending_info pending; - result.code = ledger.store.pending.get (transaction, key, pending) ? nano::process_result::unreceivable : nano::process_result::progress; // Has this source already been received (Malformed) - if (result.code == nano::process_result::progress) + auto pending = ledger.store.pending.get (transaction, key); + result = !pending ? nano::block_status::unreceivable : nano::block_status::progress; // Has this source already been received (Malformed) + if (result == nano::block_status::progress) { - result.code = block_a.hashables.account == ledger.constants.burn_account ? nano::process_result::opened_burn_account : nano::process_result::progress; // Is it burning 0 account? (Malicious) - if (result.code == nano::process_result::progress) + result = block_a.hashables.account == ledger.constants.burn_account ? nano::block_status::opened_burn_account : nano::block_status::progress; // Is it burning 0 account? (Malicious) + if (result == nano::block_status::progress) { - result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed) - if (result.code == nano::process_result::progress) + result = pending.value ().epoch == nano::epoch::epoch_0 ? nano::block_status::progress : nano::block_status::unreceivable; // Are we receiving a state-only send? (Malformed) + if (result == nano::block_status::progress) { nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) - if (result.code == nano::process_result::progress) + result = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::block_status::progress : nano::block_status::insufficient_work; // Does this block have sufficient work? (Malformed) + if (result == nano::block_status::progress) { #ifdef NDEBUG if (ledger.store.block.exists (transaction, block_a.hashables.source)) { nano::account_info source_info; - [[maybe_unused]] auto error (ledger.store.account.get (transaction, pending.source, source_info)); + [[maybe_unused]] auto error (ledger.store.account.get (transaction, pending.value ().source, source_info)); debug_assert (!error); } #endif ledger.store.pending.del (transaction, key); - block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); + block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.value ().amount, 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); ledger.store.block.put (transaction, hash, block_a); - nano::account_info new_info (hash, block_a.representative (), hash, pending.amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0); + nano::account_info new_info (hash, block_a.representative_field ().value (), hash, pending.value ().amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0); ledger.update_account (transaction, block_a.hashables.account, info, new_info); - ledger.cache.rep_weights.representation_add (block_a.representative (), pending.amount.number ()); + ledger.cache.rep_weights.representation_add (block_a.representative_field ().value (), pending.value ().amount.number ()); ledger.store.frontier.put (transaction, hash, block_a.hashables.account); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::open); } @@ -694,7 +693,7 @@ ledger_processor::ledger_processor (nano::ledger & ledger_a, nano::store::write_ class representative_visitor final : public nano::block_visitor { public: - representative_visitor (nano::store::transaction const & transaction_a, nano::store::component & store_a); + representative_visitor (nano::store::transaction const & transaction_a, nano::ledger & ledger); ~representative_visitor () = default; void compute (nano::block_hash const & hash_a); void send_block (nano::send_block const & block_a) override; @@ -703,15 +702,15 @@ class representative_visitor final : public nano::block_visitor void change_block (nano::change_block const & block_a) override; void state_block (nano::state_block const & block_a) override; nano::store::transaction const & transaction; - nano::store::component & store; + nano::ledger & ledger; nano::block_hash current; nano::block_hash result; }; -representative_visitor::representative_visitor (nano::store::transaction const & transaction_a, nano::store::component & store_a) : - transaction (transaction_a), - store (store_a), - result (0) +representative_visitor::representative_visitor (nano::store::transaction const & transaction_a, nano::ledger & ledger) : + transaction{ transaction_a }, + ledger{ ledger }, + result{ 0 } { } @@ -720,9 +719,9 @@ void representative_visitor::compute (nano::block_hash const & hash_a) current = hash_a; while (result.is_zero ()) { - auto block (store.block.get (transaction, current)); - debug_assert (block != nullptr); - block->visit (*this); + auto block_l = ledger.block (transaction, current); + debug_assert (block_l != nullptr); + block_l->visit (*this); } } @@ -752,7 +751,7 @@ void representative_visitor::state_block (nano::state_block const & block_a) } } // namespace -nano::ledger::ledger (nano::store::component & store_a, nano::stats & stat_a, nano::ledger_constants & constants, nano::generate_cache const & generate_cache_a) : +nano::ledger::ledger (nano::store::component & store_a, nano::stats & stat_a, nano::ledger_constants & constants, nano::generate_cache_flags const & generate_cache_flags_a) : constants{ constants }, store{ store_a }, stats{ stat_a }, @@ -760,13 +759,13 @@ nano::ledger::ledger (nano::store::component & store_a, nano::stats & stat_a, na { if (!store.init_error ()) { - initialize (generate_cache_a); + initialize (generate_cache_flags_a); } } -void nano::ledger::initialize (nano::generate_cache const & generate_cache_a) +void nano::ledger::initialize (nano::generate_cache_flags const & generate_cache_flags_a) { - if (generate_cache_a.reps || generate_cache_a.account_count || generate_cache_a.block_count) + if (generate_cache_flags_a.reps || generate_cache_flags_a.account_count || generate_cache_flags_a.block_count) { store.account.for_each_par ( [this] (store::read_transaction const & /*unused*/, store::iterator i, store::iterator n) { @@ -786,7 +785,7 @@ void nano::ledger::initialize (nano::generate_cache const & generate_cache_a) }); } - if (generate_cache_a.cemented_count) + if (generate_cache_flags_a.cemented_count) { store.confirmation_height.for_each_par ( [this] (store::read_transaction const & /*unused*/, store::iterator i, store::iterator n) { @@ -810,53 +809,29 @@ void nano::ledger::initialize (nano::generate_cache const & generate_cache_a) } } -nano::uint128_t nano::ledger::balance (nano::block const & block) -{ - nano::uint128_t result; - switch (block.type ()) - { - case nano::block_type::open: - case nano::block_type::receive: - case nano::block_type::change: - result = block.sideband ().balance.number (); - break; - case nano::block_type::send: - case nano::block_type::state: - result = block.balance ().number (); - break; - case nano::block_type::invalid: - case nano::block_type::not_a_block: - release_assert (false); - break; - } - return result; -} - // Balance for account containing hash -nano::uint128_t nano::ledger::balance (store::transaction const & transaction, nano::block_hash const & hash) const +std::optional nano::ledger::balance (store::transaction const & transaction, nano::block_hash const & hash) const { if (hash.is_zero ()) { - return 0; + return std::nullopt; } auto block = store.block.get (transaction, hash); - debug_assert (block != nullptr); - return balance (*block); + if (!block) + { + return std::nullopt; + } + return block->balance ().number (); } -nano::uint128_t nano::ledger::balance_safe (store::transaction const & transaction_a, nano::block_hash const & hash_a, bool & error_a) const +std::shared_ptr nano::ledger::block (store::transaction const & transaction, nano::block_hash const & hash) const { - nano::uint128_t result (0); - if (pruning && !hash_a.is_zero () && !store.block.exists (transaction_a, hash_a)) - { - error_a = true; - result = 0; - } - else - { - result = balance (transaction_a, hash_a); - } - return result; + return store.block.get (transaction, hash); +} + +bool nano::ledger::block_exists (store::transaction const & transaction, nano::block_hash const & hash) const +{ + return store.block.exists (transaction, hash); } // Balance for an account by account number @@ -868,7 +843,7 @@ nano::uint128_t nano::ledger::account_balance (store::transaction const & transa nano::confirmation_height_info info; if (!store.confirmation_height.get (transaction_a, account_a, info)) { - result = balance (transaction_a, info.frontier); + result = balance (transaction_a, info.frontier).value (); } } else @@ -906,20 +881,15 @@ nano::uint128_t nano::ledger::account_receivable (store::transaction const & tra std::optional nano::ledger::pending_info (store::transaction const & transaction, nano::pending_key const & key) const { - nano::pending_info result; - if (!store.pending.get (transaction, key, result)) - { - return result; - } - return std::nullopt; + return store.pending.get (transaction, key); } -nano::process_return nano::ledger::process (store::write_transaction const & transaction_a, nano::block & block_a) +nano::block_status nano::ledger::process (store::write_transaction const & transaction_a, std::shared_ptr block_a) { - debug_assert (!constants.work.validate_entry (block_a) || constants.genesis == nano::dev::genesis); + debug_assert (!constants.work.validate_entry (*block_a) || constants.genesis == nano::dev::genesis); ledger_processor processor (*this, transaction_a); - block_a.visit (processor); - if (processor.result.code == nano::process_result::progress) + block_a->visit (processor); + if (processor.result == nano::block_status::progress) { ++cache.block_count; } @@ -929,13 +899,13 @@ nano::process_return nano::ledger::process (store::write_transaction const & tra nano::block_hash nano::ledger::representative (store::transaction const & transaction_a, nano::block_hash const & hash_a) { auto result (representative_calculated (transaction_a, hash_a)); - debug_assert (result.is_zero () || store.block.exists (transaction_a, result)); + debug_assert (result.is_zero () || block_exists (transaction_a, result)); return result; } nano::block_hash nano::ledger::representative_calculated (store::transaction const & transaction_a, nano::block_hash const & hash_a) { - representative_visitor visitor (transaction_a, store); + representative_visitor visitor (transaction_a, *this); visitor.compute (hash_a); return visitor.result; } @@ -951,12 +921,7 @@ bool nano::ledger::block_or_pruned_exists (store::transaction const & transactio { return true; } - return store.block.exists (transaction_a, hash_a); -} - -bool nano::ledger::root_exists (store::transaction const & transaction_a, nano::root const & root_a) -{ - return store.block.exists (transaction_a, root_a.as_block_hash ()) || store.account.exists (transaction_a, root_a.as_account ()); + return block_exists (transaction_a, hash_a); } std::string nano::ledger::block_text (char const * hash_a) @@ -968,78 +933,10 @@ std::string nano::ledger::block_text (nano::block_hash const & hash_a) { std::string result; auto transaction (store.tx_begin_read ()); - auto block (store.block.get (transaction, hash_a)); - if (block != nullptr) - { - block->serialize_json (result); - } - return result; -} - -bool nano::ledger::is_send (store::transaction const & transaction_a, nano::block const & block_a) const -{ - if (block_a.type () != nano::block_type::state) + auto block_l = block (transaction, hash_a); + if (block_l != nullptr) { - return block_a.type () == nano::block_type::send; - } - nano::block_hash previous = block_a.previous (); - /* - * if block_a does not have a sideband, then is_send() - * requires that the previous block exists in the database. - * This is because it must retrieve the balance of the previous block. - */ - debug_assert (block_a.has_sideband () || previous.is_zero () || store.block.exists (transaction_a, previous)); - - bool result (false); - if (block_a.has_sideband ()) - { - result = block_a.sideband ().details.is_send; - } - else - { - if (!previous.is_zero ()) - { - if (block_a.balance () < balance (transaction_a, previous)) - { - result = true; - } - } - } - return result; -} - -nano::account const & nano::ledger::block_destination (store::transaction const & transaction_a, nano::block const & block_a) -{ - nano::send_block const * send_block (dynamic_cast (&block_a)); - nano::state_block const * state_block (dynamic_cast (&block_a)); - if (send_block != nullptr) - { - return send_block->hashables.destination; - } - else if (state_block != nullptr && is_send (transaction_a, *state_block)) - { - return state_block->hashables.link.as_account (); - } - - return nano::account::null (); -} - -nano::block_hash nano::ledger::block_source (store::transaction const & transaction_a, nano::block const & block_a) -{ - /* - * block_source() requires that the previous block of the block - * passed in exist in the database. This is because it will try - * to check account balances to determine if it is a send block. - */ - debug_assert (block_a.previous ().is_zero () || store.block.exists (transaction_a, block_a.previous ())); - - // If block_a.source () is nonzero, then we have our source. - // However, universal blocks will always return zero. - nano::block_hash result (block_a.source ()); - nano::state_block const * state_block (dynamic_cast (&block_a)); - if (state_block != nullptr && !is_send (transaction_a, *state_block)) - { - result = state_block->hashables.link.as_block_hash (); + block_l->serialize_json (result); } return result; } @@ -1097,12 +994,12 @@ nano::uint128_t nano::ledger::weight (nano::account const & account_a) // Rollback blocks until `block_a' doesn't exist or it tries to penetrate the confirmation height bool nano::ledger::rollback (store::write_transaction const & transaction_a, nano::block_hash const & block_a, std::vector> & list_a) { - debug_assert (store.block.exists (transaction_a, block_a)); - auto account_l (account (transaction_a, block_a)); + debug_assert (block_exists (transaction_a, block_a)); + auto account_l = account (transaction_a, block_a).value (); auto block_account_height (height (transaction_a, block_a)); rollback_visitor rollback (transaction_a, *this, list_a); auto error (false); - while (!error && store.block.exists (transaction_a, block_a)) + while (!error && block_exists (transaction_a, block_a)) { nano::confirmation_height_info confirmation_height_info; store.confirmation_height.get (transaction_a, account_l, confirmation_height_info); @@ -1110,9 +1007,9 @@ bool nano::ledger::rollback (store::write_transaction const & transaction_a, nan { auto info = account_info (transaction_a, account_l); debug_assert (info); - auto block (store.block.get (transaction_a, info->head)); - list_a.push_back (block); - block->visit (rollback); + auto block_l = block (transaction_a, info->head); + list_a.push_back (block_l); + block_l->visit (rollback); error = rollback.error; if (!error) { @@ -1133,87 +1030,39 @@ bool nano::ledger::rollback (store::write_transaction const & transaction_a, nan return rollback (transaction_a, block_a, rollback_list); } -nano::account nano::ledger::account (nano::block const & block) const +std::optional nano::ledger::account (store::transaction const & transaction, nano::block_hash const & hash) const { - debug_assert (block.has_sideband ()); - nano::account result (block.account ()); - if (result.is_zero ()) + auto block_l = block (transaction, hash); + if (!block_l) { - result = block.sideband ().account; + return std::nullopt; } - debug_assert (!result.is_zero ()); - return result; + return block_l->account (); } -nano::account nano::ledger::account (store::transaction const & transaction, nano::block_hash const & hash) const +std::optional nano::ledger::account_info (store::transaction const & transaction, nano::account const & account) const { - auto block = store.block.get (transaction, hash); - debug_assert (block != nullptr); - return account (*block); + return store.account.get (transaction, account); } -nano::account nano::ledger::account_safe (store::transaction const & transaction_a, nano::block_hash const & hash_a, bool & error_a) const +std::optional nano::ledger::amount (store::transaction const & transaction_a, nano::block_hash const & hash_a) { - if (!pruning) - { - return account (transaction_a, hash_a); - } - else + auto block_l = block (transaction_a, hash_a); + if (!block_l) { - auto block (store.block.get (transaction_a, hash_a)); - if (block != nullptr) - { - return account (*block); - } - else - { - error_a = true; - return 0; - } + return std::nullopt; } -} - -nano::account nano::ledger::account_safe (store::transaction const & transaction, nano::block_hash const & hash) const -{ - auto block = store.block.get (transaction, hash); - if (block) + auto block_balance = block_l->balance (); + if (block_l->previous ().is_zero ()) { - return account (*block); + return block_balance.number (); } - else + auto previous_balance = balance (transaction_a, block_l->previous ()); + if (!previous_balance) { - return { 0 }; + return std::nullopt; } -} - -std::optional nano::ledger::account_info (store::transaction const & transaction, nano::account const & account) const -{ - return store.account.get (transaction, account); -} - -// Return amount decrease or increase for block -nano::uint128_t nano::ledger::amount (store::transaction const & transaction_a, nano::account const & account_a) -{ - release_assert (account_a == constants.genesis->account ()); - return nano::dev::constants.genesis_amount; -} - -nano::uint128_t nano::ledger::amount (store::transaction const & transaction_a, nano::block_hash const & hash_a) -{ - auto block (store.block.get (transaction_a, hash_a)); - auto block_balance (balance (transaction_a, hash_a)); - auto previous_balance (balance (transaction_a, block->previous ())); - return block_balance > previous_balance ? block_balance - previous_balance : previous_balance - block_balance; -} - -nano::uint128_t nano::ledger::amount_safe (store::transaction const & transaction_a, nano::block_hash const & hash_a, bool & error_a) const -{ - auto block (store.block.get (transaction_a, hash_a)); - debug_assert (block); - auto block_balance (balance (transaction_a, hash_a)); - auto previous_balance (balance_safe (transaction_a, block->previous (), error_a)); - return error_a ? 0 : block_balance > previous_balance ? block_balance - previous_balance - : previous_balance - block_balance; + return block_balance > previous_balance.value () ? block_balance.number () - previous_balance.value () : previous_balance.value () - block_balance.number (); } // Return latest block for account @@ -1243,21 +1092,13 @@ void nano::ledger::dump_account_chain (nano::account const & account_a, std::ost auto hash (latest (transaction, account_a)); while (!hash.is_zero ()) { - auto block (store.block.get (transaction, hash)); - debug_assert (block != nullptr); + auto block_l = block (transaction, hash); + debug_assert (block_l != nullptr); stream << hash.to_string () << std::endl; - hash = block->previous (); + hash = block_l->previous (); } } -bool nano::ledger::could_fit (store::transaction const & transaction_a, nano::block const & block_a) const -{ - auto dependencies (dependent_blocks (transaction_a, block_a)); - return std::all_of (dependencies.begin (), dependencies.end (), [this, &transaction_a] (nano::block_hash const & hash_a) { - return hash_a.is_zero () || store.block.exists (transaction_a, hash_a); - }); -} - bool nano::ledger::dependents_confirmed (store::transaction const & transaction_a, nano::block const & block_a) const { auto dependencies (dependent_blocks (transaction_a, block_a)); @@ -1292,13 +1133,13 @@ class dependent_block_visitor : public nano::block_visitor void receive_block (nano::receive_block const & block_a) override { result[0] = block_a.previous (); - result[1] = block_a.source (); + result[1] = block_a.source_field ().value (); } void open_block (nano::open_block const & block_a) override { - if (block_a.source () != ledger.constants.genesis->account ()) + if (block_a.source_field ().value () != ledger.constants.genesis->account ()) { - result[0] = block_a.source (); + result[0] = block_a.source_field ().value (); } } void change_block (nano::change_block const & block_a) override @@ -1310,11 +1151,25 @@ class dependent_block_visitor : public nano::block_visitor result[0] = block_a.hashables.previous; result[1] = block_a.hashables.link.as_block_hash (); // ledger.is_send will check the sideband first, if block_a has a loaded sideband the check that previous block exists can be skipped - if (ledger.is_epoch_link (block_a.hashables.link) || ((block_a.has_sideband () || ledger.store.block.exists (transaction, block_a.hashables.previous)) && ledger.is_send (transaction, block_a))) + if (ledger.is_epoch_link (block_a.hashables.link) || is_send (transaction, block_a)) { result[1].clear (); } } + // This function is used in place of block->is_send () as it is tolerant to the block not having the sideband information loaded + // This is needed for instance in vote generation on forks which have not yet had sideband information attached + bool is_send (nano::store::transaction const & transaction, nano::state_block const & block) const + { + if (block.previous ().is_zero ()) + { + return false; + } + if (block.has_sideband ()) + { + return block.sideband ().details.is_send; + } + return block.balance_field ().value () < ledger.balance (transaction, block.previous ()); + } nano::ledger const & ledger; nano::store::transaction const & transaction; std::array result; @@ -1342,34 +1197,19 @@ std::shared_ptr nano::ledger::find_receive_block_by_send_hash (stor { return nullptr; } - auto possible_receive_block = store.block.get (transaction, info.frontier); + auto possible_receive_block = block (transaction, info.frontier); // walk down the chain until the source field of a receive block matches the send block hash while (possible_receive_block != nullptr) { - // if source is non-zero then it is a legacy receive or open block - nano::block_hash source = possible_receive_block->source (); - - // if source is zero then it could be a state block, which needs a different kind of access - auto state_block = dynamic_cast (possible_receive_block.get ()); - if (state_block != nullptr) - { - // we read the block from the database, so we expect it to have sideband - debug_assert (state_block->has_sideband ()); - if (state_block->sideband ().details.is_receive) - { - source = state_block->hashables.link.as_block_hash (); - } - } - - if (send_block_hash == source) + if (possible_receive_block->is_receive () && send_block_hash == possible_receive_block->source ()) { // we have a match result = possible_receive_block; break; } - possible_receive_block = store.block.get (transaction, possible_receive_block->previous ()); + possible_receive_block = block (transaction, possible_receive_block->previous ()); } return result; @@ -1437,7 +1277,7 @@ std::shared_ptr nano::ledger::successor (store::transaction const & std::shared_ptr result; if (!successor.is_zero ()) { - result = store.block.get (transaction_a, successor); + result = block (transaction_a, successor); } debug_assert (successor.is_zero () || result != nullptr); return result; @@ -1445,15 +1285,15 @@ std::shared_ptr nano::ledger::successor (store::transaction const & std::shared_ptr nano::ledger::forked_block (store::transaction const & transaction_a, nano::block const & block_a) { - debug_assert (!store.block.exists (transaction_a, block_a.hash ())); + debug_assert (!block_exists (transaction_a, block_a.hash ())); auto root (block_a.root ()); - debug_assert (store.block.exists (transaction_a, root.as_block_hash ()) || store.account.exists (transaction_a, root.as_account ())); - auto result (store.block.get (transaction_a, store.block.successor (transaction_a, root.as_block_hash ()))); + debug_assert (block_exists (transaction_a, root.as_block_hash ()) || store.account.exists (transaction_a, root.as_account ())); + auto result = block (transaction_a, store.block.successor (transaction_a, root.as_block_hash ())); if (result == nullptr) { auto info = account_info (transaction_a, root.as_account ()); debug_assert (info); - result = store.block.get (transaction_a, info->open_block); + result = block (transaction_a, info->open_block); debug_assert (result != nullptr); } return result; @@ -1464,7 +1304,7 @@ std::shared_ptr nano::ledger::head_block (store::transaction const auto info = store.account.get (transaction, account); if (info) { - return store.block.get (transaction, info->head); + return block (transaction, info->head); } return nullptr; } @@ -1475,12 +1315,12 @@ bool nano::ledger::block_confirmed (store::transaction const & transaction_a, na { return true; } - auto block = store.block.get (transaction_a, hash_a); - if (block) + auto block_l = block (transaction_a, hash_a); + if (block_l) { nano::confirmation_height_info confirmation_height_info; - store.confirmation_height.get (transaction_a, block->account ().is_zero () ? block->sideband ().account : block->account (), confirmation_height_info); - auto confirmed (confirmation_height_info.height >= block->sideband ().height); + store.confirmation_height.get (transaction_a, block_l->account (), confirmation_height_info); + auto confirmed (confirmation_height_info.height >= block_l->sideband ().height); return confirmed; } return false; @@ -1492,12 +1332,12 @@ uint64_t nano::ledger::pruning_action (store::write_transaction & transaction_a, nano::block_hash hash (hash_a); while (!hash.is_zero () && hash != constants.genesis->hash ()) { - auto block (store.block.get (transaction_a, hash)); - if (block != nullptr) + auto block_l = block (transaction_a, hash); + if (block_l != nullptr) { store.block.del (transaction_a, hash); store.pruned.put (transaction_a, hash); - hash = block->previous (); + hash = block_l->previous (); ++pruned_count; ++cache.pruned_count; if (pruned_count % batch_size_a == 0) @@ -1558,7 +1398,7 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p auto rockdb_data_path = data_path_a / "rocksdb"; std::filesystem::remove_all (rockdb_data_path); - nano::logger_mt logger; + nano::logger logger; auto error (false); // Open rocksdb database @@ -1664,7 +1504,7 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p auto random_block (store.block.random (lmdb_transaction)); error |= rocksdb_store->block.get (rocksdb_transaction, random_block->hash ()) == nullptr; - auto account = random_block->account ().is_zero () ? random_block->sideband ().account : random_block->account (); + auto account = random_block->account (); nano::account_info account_info; error |= rocksdb_store->account.get (rocksdb_transaction, account, account_info); @@ -1699,18 +1539,18 @@ nano::epoch nano::ledger::version (nano::block const & block) nano::epoch nano::ledger::version (store::transaction const & transaction, nano::block_hash const & hash) const { - auto block = store.block.get (transaction, hash); - if (block == nullptr) + auto block_l = block (transaction, hash); + if (block_l == nullptr) { return nano::epoch::epoch_0; } - return version (*block); + return version (*block_l); } uint64_t nano::ledger::height (store::transaction const & transaction, nano::block_hash const & hash) const { - auto block = store.block.get (transaction, hash); - return block->sideband ().height; + auto block_l = block (transaction, hash); + return block_l->sideband ().height; } nano::uncemented_info::uncemented_info (nano::block_hash const & cemented_frontier, nano::block_hash const & frontier, nano::account const & account) : diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index c1e2b11817..cf6e6515be 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -1,8 +1,10 @@ #pragma once -#include +#include #include -#include +#include +#include +#include #include @@ -15,11 +17,14 @@ class write_transaction; namespace nano { +class block; +enum class block_status; +enum class epoch : uint8_t; +class ledger_constants; +class pending_info; +class pending_key; class stats; -// map of vote weight per block, ordered greater first -using tally_t = std::map, std::greater>; - class uncemented_info { public: @@ -32,29 +37,17 @@ class uncemented_info class ledger final { public: - ledger (nano::store::component &, nano::stats &, nano::ledger_constants & constants, nano::generate_cache const & = nano::generate_cache ()); + ledger (nano::store::component &, nano::stats &, nano::ledger_constants & constants, nano::generate_cache_flags const & = nano::generate_cache_flags{}); /** - * Return account containing hash, expects that block hash exists in ledger + * Returns the account for a given hash + * Returns std::nullopt if the block doesn't exist or has been pruned */ - nano::account account (nano::block const & block) const; - nano::account account (store::transaction const &, nano::block_hash const &) const; + std::optional account (store::transaction const &, nano::block_hash const &) const; std::optional account_info (store::transaction const & transaction, nano::account const & account) const; - /** - * For non-prunning nodes same as `ledger::account()` - * For prunning nodes ensures that block hash exists, otherwise returns zero account - */ - nano::account account_safe (store::transaction const &, nano::block_hash const &, bool &) const; - /** - * Return account containing hash, returns zero account if account can not be found - */ - nano::account account_safe (store::transaction const &, nano::block_hash const &) const; - nano::uint128_t amount (store::transaction const &, nano::account const &); - nano::uint128_t amount (store::transaction const &, nano::block_hash const &); - /** Safe for previous block, but block hash_a must exist */ - nano::uint128_t amount_safe (store::transaction const &, nano::block_hash const & hash_a, bool &) const; - static nano::uint128_t balance (nano::block const & block); - nano::uint128_t balance (store::transaction const &, nano::block_hash const &) const; - nano::uint128_t balance_safe (store::transaction const &, nano::block_hash const &, bool &) const; + std::optional amount (store::transaction const &, nano::block_hash const &); + std::optional balance (store::transaction const &, nano::block_hash const &) const; + std::shared_ptr block (store::transaction const & transaction, nano::block_hash const & hash) const; + bool block_exists (store::transaction const & transaction, nano::block_hash const & hash) const; nano::uint128_t account_balance (store::transaction const &, nano::account const &, bool = false); nano::uint128_t account_receivable (store::transaction const &, nano::account const &, bool = false); nano::uint128_t weight (nano::account const &); @@ -68,21 +61,16 @@ class ledger final nano::block_hash representative_calculated (store::transaction const &, nano::block_hash const &); bool block_or_pruned_exists (nano::block_hash const &) const; bool block_or_pruned_exists (store::transaction const &, nano::block_hash const &) const; - bool root_exists (store::transaction const &, nano::root const &); std::string block_text (char const *); std::string block_text (nano::block_hash const &); - bool is_send (store::transaction const &, nano::block const &) const; - nano::account const & block_destination (store::transaction const &, nano::block const &); - nano::block_hash block_source (store::transaction const &, nano::block const &); std::pair hash_root_random (store::transaction const &) const; std::optional pending_info (store::transaction const & transaction, nano::pending_key const & key) const; - nano::process_return process (store::write_transaction const &, nano::block &); + nano::block_status process (store::write_transaction const & transaction, std::shared_ptr block); bool rollback (store::write_transaction const &, nano::block_hash const &, std::vector> &); bool rollback (store::write_transaction const &, nano::block_hash const &); void update_account (store::write_transaction const &, nano::account const &, nano::account_info const &, nano::account_info const &); uint64_t pruning_action (store::write_transaction &, nano::block_hash const &, uint64_t const); void dump_account_chain (nano::account const &, std::ostream & = std::cout); - bool could_fit (store::transaction const &, nano::block const &) const; bool dependents_confirmed (store::transaction const &, nano::block const &) const; bool is_epoch_link (nano::link const &) const; std::array dependent_blocks (store::transaction const &, nano::block const &) const; @@ -106,7 +94,7 @@ class ledger final bool pruning{ false }; private: - void initialize (nano::generate_cache const &); + void initialize (nano::generate_cache_flags const &); }; std::unique_ptr collect_container_info (ledger & ledger, std::string const & name); diff --git a/nano/secure/ledger_cache.cpp b/nano/secure/ledger_cache.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nano/secure/ledger_cache.hpp b/nano/secure/ledger_cache.hpp new file mode 100644 index 0000000000..726a1e1119 --- /dev/null +++ b/nano/secure/ledger_cache.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include + +namespace nano +{ +/* Holds an in-memory cache of various counts */ +class ledger_cache +{ +public: + nano::rep_weights rep_weights; + std::atomic cemented_count{ 0 }; + std::atomic block_count{ 0 }; + std::atomic pruned_count{ 0 }; + std::atomic account_count{ 0 }; + std::atomic final_votes_confirmation_canary{ false }; +}; +} diff --git a/nano/secure/network_filter.cpp b/nano/secure/network_filter.cpp index 059cddb30e..c60a111749 100644 --- a/nano/secure/network_filter.cpp +++ b/nano/secure/network_filter.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/nano/secure/pending_info.cpp b/nano/secure/pending_info.cpp new file mode 100644 index 0000000000..637f4adf74 --- /dev/null +++ b/nano/secure/pending_info.cpp @@ -0,0 +1,72 @@ +#include + +nano::pending_info::pending_info (nano::account const & source_a, nano::amount const & amount_a, nano::epoch epoch_a) : + source (source_a), + amount (amount_a), + epoch (epoch_a) +{ +} + +bool nano::pending_info::deserialize (nano::stream & stream_a) +{ + auto error (false); + try + { + nano::read (stream_a, source.bytes); + nano::read (stream_a, amount.bytes); + nano::read (stream_a, epoch); + } + catch (std::runtime_error const &) + { + error = true; + } + + return error; +} + +size_t nano::pending_info::db_size () const +{ + return sizeof (source) + sizeof (amount) + sizeof (epoch); +} + +bool nano::pending_info::operator== (nano::pending_info const & other_a) const +{ + return source == other_a.source && amount == other_a.amount && epoch == other_a.epoch; +} + +nano::pending_key::pending_key (nano::account const & account_a, nano::block_hash const & hash_a) : + account (account_a), + hash (hash_a) +{ +} + +bool nano::pending_key::deserialize (nano::stream & stream_a) +{ + auto error (false); + try + { + nano::read (stream_a, account.bytes); + nano::read (stream_a, hash.bytes); + } + catch (std::runtime_error const &) + { + error = true; + } + + return error; +} + +bool nano::pending_key::operator== (nano::pending_key const & other_a) const +{ + return account == other_a.account && hash == other_a.hash; +} + +nano::account const & nano::pending_key::key () const +{ + return account; +} + +bool nano::pending_key::operator< (nano::pending_key const & other_a) const +{ + return account == other_a.account ? hash < other_a.hash : account < other_a.account; +} diff --git a/nano/secure/pending_info.hpp b/nano/secure/pending_info.hpp new file mode 100644 index 0000000000..584337e95e --- /dev/null +++ b/nano/secure/pending_info.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +namespace nano +{ +/** + * Information on an uncollected send + */ +class pending_info final +{ +public: + pending_info () = default; + pending_info (nano::account const &, nano::amount const &, nano::epoch); + size_t db_size () const; + bool deserialize (nano::stream &); + bool operator== (nano::pending_info const &) const; + nano::account source{}; + nano::amount amount{ 0 }; + nano::epoch epoch{ nano::epoch::epoch_0 }; +}; +class pending_key final +{ +public: + pending_key () = default; + pending_key (nano::account const &, nano::block_hash const &); + bool deserialize (nano::stream &); + bool operator== (nano::pending_key const &) const; + bool operator< (nano::pending_key const &) const; + nano::account const & key () const; + nano::account account{}; + nano::block_hash hash{ 0 }; +}; +} // namespace nano + +namespace std +{ +template <> +struct hash<::nano::pending_key> +{ + size_t operator() (::nano::pending_key const & data_a) const + { + return hash<::nano::uint512_union>{}({ ::nano::uint256_union{ data_a.account.number () }, data_a.hash }); + } +}; +} diff --git a/nano/secure/utility.cpp b/nano/secure/utility.cpp index 19c5836294..07d6472462 100644 --- a/nano/secure/utility.cpp +++ b/nano/secure/utility.cpp @@ -2,6 +2,8 @@ #include #include +#include + #include static std::vector all_unique_paths; @@ -9,6 +11,13 @@ static std::vector all_unique_paths; std::filesystem::path nano::working_path (nano::networks network) { auto result (nano::app_path ()); + + if (auto path_override = nano::get_env ("NANO_APP_PATH")) + { + result = *path_override; + std::cerr << "Application path overridden by NANO_APP_PATH environment variable: " << result << std::endl; + } + switch (network) { case nano::networks::invalid: @@ -46,6 +55,9 @@ std::filesystem::path nano::unique_path (nano::networks network) } auto result = working_path (network) / random_string; + + std::filesystem::create_directories (result); + all_unique_paths.push_back (result); return result; } @@ -60,15 +72,6 @@ void nano::remove_temporary_directories () { std::cerr << "Could not remove temporary directory: " << ec.message () << std::endl; } - - // lmdb creates a -lock suffixed file for its MDB_NOSUBDIR databases - auto lockfile = path; - lockfile += "-lock"; - std::filesystem::remove (lockfile, ec); - if (ec) - { - std::cerr << "Could not remove temporary lock file: " << ec.message () << std::endl; - } } } diff --git a/nano/secure/vote.cpp b/nano/secure/vote.cpp index 2f19c9748e..28002f25f0 100644 --- a/nano/secure/vote.cpp +++ b/nano/secure/vote.cpp @@ -165,13 +165,9 @@ std::string nano::vote::to_json () const std::string nano::vote::hashes_string () const { - std::string result; - for (auto const & hash : hashes) - { - result += hash.to_string (); - result += ", "; - } - return result; + return nano::util::join (hashes, ", ", [] (auto const & hash) { + return hash.to_string (); + }); } uint64_t nano::vote::packed_timestamp (uint64_t timestamp, uint8_t duration) @@ -186,11 +182,10 @@ bool nano::vote::is_final_timestamp (uint64_t timestamp) return timestamp == std::numeric_limits::max (); } -/* - * iterate_vote_blocks_as_hash - */ - -nano::block_hash nano::iterate_vote_blocks_as_hash::operator() (nano::block_hash const & item) const +void nano::vote::operator() (nano::object_stream & obs) const { - return item; -} + obs.write ("account", account); + obs.write ("final", is_final_timestamp (timestamp_m)); + obs.write ("timestamp", timestamp_m); + obs.write_range ("hashes", hashes); +} \ No newline at end of file diff --git a/nano/secure/vote.hpp b/nano/secure/vote.hpp index 35d7308a13..9ae7b0689f 100644 --- a/nano/secure/vote.hpp +++ b/nano/secure/vote.hpp @@ -12,14 +12,6 @@ namespace nano { -using vote_blocks_vec_iter = std::vector::const_iterator; -class iterate_vote_blocks_as_hash final -{ -public: - iterate_vote_blocks_as_hash () = default; - nano::block_hash operator() (nano::block_hash const & item) const; -}; - class vote final { public: @@ -43,9 +35,6 @@ class vote final bool operator== (nano::vote const &) const; bool operator!= (nano::vote const &) const; - boost::transform_iterator begin () const; - boost::transform_iterator end () const; - void serialize_json (boost::property_tree::ptree & tree) const; std::string to_json () const; std::string hashes_string () const; @@ -82,6 +71,9 @@ class vote final static std::string const hash_prefix; static uint64_t packed_timestamp (uint64_t timestamp, uint8_t duration); + +public: // Logging + void operator() (nano::object_stream &) const; }; using vote_uniquer = nano::uniquer; diff --git a/nano/slow_test/bootstrap.cpp b/nano/slow_test/bootstrap.cpp index b500e4a009..6492ad6bd4 100644 --- a/nano/slow_test/bootstrap.cpp +++ b/nano/slow_test/bootstrap.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,7 @@ TEST (bootstrap_ascending, profile) flags_server.disable_ongoing_bootstrap = true; flags_server.disable_ascending_bootstrap = true; auto data_path_server = nano::working_path (network); - //auto data_path_server = ""; + // auto data_path_server = ""; auto server = std::make_shared (system.io_ctx, data_path_server, config_server, system.work, flags_server); system.nodes.push_back (server); server->start (); @@ -93,10 +94,10 @@ TEST (bootstrap_ascending, profile) config_client.ipc_config.transport_tcp.enabled = true; // Disable database integrity safety for higher throughput config_client.lmdb_config.sync = nano::lmdb_config::sync_strategy::nosync_unsafe; - //auto client = system.add_node (config_client, flags_client); + // auto client = system.add_node (config_client, flags_client); // macos 16GB RAM disk: diskutil erasevolume HFS+ "RAMDisk" `hdiutil attach -nomount ram://33554432` - //auto data_path_client = "/Volumes/RAMDisk"; + // auto data_path_client = "/Volumes/RAMDisk"; auto data_path_client = nano::unique_path (); auto client = std::make_shared (system.io_ctx, data_path_client, config_client, system.work, flags_client); system.nodes.push_back (client); @@ -186,7 +187,7 @@ TEST (bootstrap_ascending, profile) rate.observe (*client, nano::stat::type::ledger, nano::stat::detail::gap_previous, nano::stat::dir::in); rate.background_print (3s); - //wait_for_key (); + // wait_for_key (); while (true) { nano::test::establish_tcp (system, *client, server->network.endpoint ()); diff --git a/nano/slow_test/entry.cpp b/nano/slow_test/entry.cpp index cc8fd2e18e..0b9a0ca758 100644 --- a/nano/slow_test/entry.cpp +++ b/nano/slow_test/entry.cpp @@ -1,6 +1,8 @@ +#include #include #include + namespace nano { namespace test @@ -12,6 +14,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; testing::InitGoogleTest (&argc, argv); diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index 2bb0075c01..06b8728ebf 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -7,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -88,7 +91,7 @@ TEST (system, receive_while_synchronizing) uint32_t count (1000); system.generate_mass_activity (count, *system.nodes[0]); nano::keypair key; - auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.logging, system.work)); + auto node1 (std::make_shared (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work)); ASSERT_FALSE (node1->init_error ()); auto wallet (node1->wallets.create (1)); wallet->insert_adhoc (nano::dev::genesis_key.prv); // For voting @@ -99,7 +102,7 @@ TEST (system, receive_while_synchronizing) node1->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (200), ([&system, &key] () { auto hash (system.wallet (0)->send_sync (nano::dev::genesis_key.pub, key.pub, system.nodes[0]->config.receive_minimum.number ())); auto transaction (system.nodes[0]->store.tx_begin_read ()); - auto block (system.nodes[0]->store.block.get (transaction, hash)); + auto block = system.nodes[0]->ledger.block (transaction, hash); std::string block_text; block->serialize_json (block_text); })); @@ -116,7 +119,7 @@ TEST (system, receive_while_synchronizing) TEST (ledger, deep_account_compute) { - nano::logger_mt logger; + nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_FALSE (store->init_error ()); nano::stats stats; @@ -135,7 +138,7 @@ TEST (ledger, deep_account_compute) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto open = builder .open () .source (send->hash ()) @@ -144,7 +147,7 @@ TEST (ledger, deep_account_compute) .sign (key.prv, key.pub) .work (*pool.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); auto sprevious (send->hash ()); auto rprevious (open->hash ()); for (auto i (0), n (100000); i != n; ++i) @@ -158,7 +161,7 @@ TEST (ledger, deep_account_compute) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (sprevious)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); sprevious = send->hash (); auto receive = builder .receive () @@ -167,7 +170,7 @@ TEST (ledger, deep_account_compute) .sign (key.prv, key.pub) .work (*pool.generate (rprevious)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive)); rprevious = receive->hash (); if (i % 100 == 0) { @@ -276,8 +279,8 @@ TEST (node, fork_storm) previous = send->hash (); for (auto node_i : system.nodes) { - auto send_result (node_i->process (*send)); - ASSERT_EQ (nano::process_result::progress, send_result.code); + auto send_result (node_i->process (send)); + ASSERT_EQ (nano::block_status::progress, send_result); nano::keypair rep; auto open = builder .open () @@ -286,10 +289,10 @@ TEST (node, fork_storm) .account (key.pub) .sign (key.prv, key.pub) .work (0) - .build_shared (); + .build (); node_i->work_generate_blocking (*open); - auto open_result (node_i->process (*open)); - ASSERT_EQ (nano::process_result::progress, open_result.code); + auto open_result (node_i->process (open)); + ASSERT_EQ (nano::block_status::progress, open_result); auto transaction (node_i->store.tx_begin_read ()); node_i->network.flood_block (open); } @@ -506,7 +509,7 @@ TEST (store, unchecked_load) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (0) - .build_shared (); + .build (); constexpr auto num_unchecked = 1'000'000; for (auto i (0); i < num_unchecked; ++i) { @@ -536,7 +539,7 @@ TEST (store, vote_load) */ TEST (store, pruned_load) { - nano::logger_mt logger; + nano::logger logger; auto path (nano::unique_path ()); constexpr auto num_pruned = 2000000; auto const expected_result = num_pruned / 2; @@ -617,7 +620,7 @@ TEST (node, mass_vote_by_hash) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous)) - .build_shared (); + .build (); previous = block->hash (); blocks.push_back (block); } @@ -659,7 +662,7 @@ TEST (confirmation_height, many_accounts_single_confirmation) .sign (last_keypair.prv, last_keypair.pub) .work (*system.work.generate (last_open_hash)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); auto open = builder .open () .source (send->hash ()) @@ -668,7 +671,7 @@ TEST (confirmation_height, many_accounts_single_confirmation) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); last_open_hash = open->hash (); last_keypair = key; } @@ -743,7 +746,7 @@ TEST (confirmation_height, many_accounts_many_confirmations) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_genesis)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); auto open = builder .open () .source (send->hash ()) @@ -751,8 +754,8 @@ TEST (confirmation_height, many_accounts_many_confirmations) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); open_blocks.push_back (std::move (open)); latest_genesis = send->hash (); } @@ -818,15 +821,15 @@ TEST (confirmation_height, long_chains) auto open = builder .open () .source (send->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .account (key1.pub) .sign (key1.prv, key1.pub) .work (*system.work.generate (key1.pub)) .build (); { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); } // Bulk send from genesis account to destination account @@ -844,7 +847,7 @@ TEST (confirmation_height, long_chains) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous_genesis_chain_hash)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); auto receive = builder .receive () .previous (previous_destination_chain_hash) @@ -852,7 +855,7 @@ TEST (confirmation_height, long_chains) .sign (key1.prv, key1.pub) .work (*system.work.generate (previous_destination_chain_hash)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive)); previous_genesis_chain_hash = send->hash (); previous_destination_chain_hash = receive->hash (); @@ -872,20 +875,20 @@ TEST (confirmation_height, long_chains) .state () .account (nano::dev::genesis_key.pub) .previous (previous_genesis_chain_hash) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio + 1) .link (send1->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (previous_genesis_chain_hash)) - .build_shared (); + .build (); // Unpocketed. Send to a non-existing account to prevent auto receives from the wallet adjusting expected confirmation height nano::keypair key2; auto send2 = builder .state () - .account (nano::dev::genesis->account ()) + .account (nano::dev::genesis_key.pub) .previous (receive1->hash ()) - .representative (nano::dev::genesis->account ()) + .representative (nano::dev::genesis_key.pub) .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) .link (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) @@ -894,9 +897,9 @@ TEST (confirmation_height, long_chains) { auto transaction = node->store.tx_begin_write (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *receive1).code); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send2).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, receive1)); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send2)); } // Call block confirm on the existing receive block on the genesis account which will confirm everything underneath on both accounts @@ -961,7 +964,7 @@ TEST (confirmation_height, dynamic_algorithm) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_genesis->hash ())) - .build_shared (); + .build (); latest_genesis = send; state_blocks.push_back (send); } @@ -969,7 +972,7 @@ TEST (confirmation_height, dynamic_algorithm) auto transaction = node->store.tx_begin_write (); for (auto const & block : state_blocks) { - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *block).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, block)); } } @@ -1027,10 +1030,10 @@ TEST (confirmation_height, dynamic_algorithm_no_transition_while_pending) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_genesis)) - .build_shared (); + .build (); latest_genesis = send->hash (); state_blocks.push_back (send); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); ++num; }; @@ -1115,7 +1118,7 @@ TEST (confirmation_height, many_accounts_send_receive_self) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_genesis)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); auto open = builder .open () .source (send->hash ()) @@ -1123,8 +1126,8 @@ TEST (confirmation_height, many_accounts_send_receive_self) .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, open)); open_blocks.push_back (std::move (open)); latest_genesis = send->hash (); } @@ -1160,14 +1163,14 @@ TEST (confirmation_height, many_accounts_send_receive_self) .balance (1) .sign (keypair.prv, keypair.pub) .work (*system.work.generate (open_block->hash ())) - .build_shared ()); + .build ()); receive_blocks.emplace_back (builder .receive () .previous (send_blocks.back ()->hash ()) .source (send_blocks.back ()->hash ()) .sign (keypair.prv, keypair.pub) .work (*system.work.generate (send_blocks.back ()->hash ())) - .build_shared ()); + .build ()); } // Now send and receive to self @@ -1222,8 +1225,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) // Don't test this in rocksdb mode return; } - nano::logger_mt logger; - nano::logging logging; + nano::logger logger; auto path (nano::unique_path ()); auto store = nano::make_store (logger, path, nano::dev::constants); ASSERT_TRUE (!store->init_error ()); @@ -1235,7 +1237,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) boost::latch initialized_latch{ 0 }; nano::block_hash block_hash_being_processed{ 0 }; - nano::confirmation_height_processor confirmation_height_processor{ ledger, write_database_queue, 10ms, logging, logger, initialized_latch, confirmation_height_mode::automatic }; + nano::confirmation_height_processor confirmation_height_processor{ ledger, write_database_queue, 10ms, logger, initialized_latch, confirmation_height_mode::automatic }; auto const num_accounts = 100000; @@ -1263,7 +1265,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (latest_genesis)) .build (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send)); auto open = builder .open () .source (send->hash ()) @@ -1271,8 +1273,8 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) .account (key.pub) .sign (key.prv, key.pub) .work (*pool.generate (key.pub)) - .build_shared (); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *open).code); + .build (); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open)); open_blocks.push_back (std::move (open)); latest_genesis = send->hash (); } @@ -1307,17 +1309,17 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) .balance (1) .sign (keypair.prv, keypair.pub) .work (*system.work.generate (open_block->hash ())) - .build_shared ()); + .build ()); receive_blocks.emplace_back (builder .receive () .previous (send_blocks.back ()->hash ()) .source (send_blocks.back ()->hash ()) .sign (keypair.prv, keypair.pub) .work (*system.work.generate (send_blocks.back ()->hash ())) - .build_shared ()); + .build ()); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send_blocks.back ()).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive_blocks.back ()).code); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send_blocks.back ())); + ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive_blocks.back ())); } } @@ -1523,7 +1525,7 @@ TEST (telemetry, under_load) .link (key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest_genesis)) - .build_shared (); + .build (); node->process_active (send); latest_genesis = send->hash (); auto open = builder @@ -1535,7 +1537,7 @@ TEST (telemetry, under_load) .link (send->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); node->process_active (open); auto latest_key = open->hash (); @@ -1553,7 +1555,7 @@ TEST (telemetry, under_load) .link (key1.pub) .sign (keypair.prv, keypair.pub) .work (*system.work.generate (latest_l)) - .build_shared (); + .build (); latest_l = send->hash (); node->process_active (send); } @@ -1688,7 +1690,7 @@ TEST (telemetry, many_nodes) for (auto node : system.nodes) { auto transaction (node->store.tx_begin_write ()); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); } // This is the node which will request metrics from all other nodes @@ -1788,7 +1790,7 @@ TEST (node, mass_epoch_upgrader) .build (ec); ASSERT_FALSE (ec); ASSERT_NE (nullptr, block); - ASSERT_EQ (nano::process_result::progress, node.process (*block).code); + ASSERT_EQ (nano::block_status::progress, node.process (block)); latest = block->hash (); info.pending_hash = block->hash (); } @@ -1812,7 +1814,7 @@ TEST (node, mass_epoch_upgrader) .build (ec); ASSERT_FALSE (ec); ASSERT_NE (nullptr, block); - ASSERT_EQ (nano::process_result::progress, node.process (*block).code); + ASSERT_EQ (nano::block_status::progress, node.process (block)); } ASSERT_EQ (1 + total_accounts + opened.size (), node.ledger.cache.block_count); ASSERT_EQ (1 + opened.size (), node.ledger.cache.account_count); @@ -1887,7 +1889,10 @@ TEST (node, mass_block_new) } ASSERT_TIMELY_EQ (200s, node.ledger.cache.block_count, next_block_count); next_block_count += num_blocks; - node.block_processor.flush (); + while (node.block_processor.size () > 0) + { + std::this_thread::sleep_for (std::chrono::milliseconds{ 100 }); + } // Clear all active { nano::lock_guard guard{ node.active.mutex }; @@ -2039,8 +2044,8 @@ TEST (node, aggressive_flooding) { for (auto const & block : genesis_blocks) { - auto process_result (node_wallet.first->process (*block)); - ASSERT_TRUE (nano::process_result::progress == process_result.code || nano::process_result::old == process_result.code); + auto process_result (node_wallet.first->process (block)); + ASSERT_TRUE (nano::block_status::progress == process_result || nano::block_status::old == process_result); } ASSERT_EQ (node1.latest (nano::dev::genesis_key.pub), node_wallet.first->latest (nano::dev::genesis_key.pub)); ASSERT_EQ (genesis_blocks.back ()->hash (), node_wallet.first->latest (nano::dev::genesis_key.pub)); @@ -2080,7 +2085,7 @@ TEST (node, aggressive_flooding) .build (); } // Processing locally goes through the aggressive block flooding path - ASSERT_EQ (nano::process_result::progress, node1.process_local (block).value ().code); + ASSERT_EQ (nano::block_status::progress, node1.process_local (block).value ()); auto all_have_block = [&nodes_wallets] (nano::block_hash const & hash_a) { return std::all_of (nodes_wallets.begin (), nodes_wallets.end (), [hash = hash_a] (auto const & node_wallet) { @@ -2123,7 +2128,7 @@ TEST (node, wallet_create_block_confirm_conflicts) { nano::test::system system; nano::block_builder builder; - nano::node_config node_config (system.get_available_port (), system.logging); + nano::node_config node_config (system.get_available_port ()); node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto node = system.add_node (node_config); auto const num_blocks = 10000; @@ -2143,7 +2148,7 @@ TEST (node, wallet_create_block_confirm_conflicts) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) .build (); - ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *send).code); + ASSERT_EQ (nano::block_status::progress, node->ledger.process (transaction, send)); latest = send->hash (); } } @@ -2159,7 +2164,7 @@ TEST (node, wallet_create_block_confirm_conflicts) // Call block confirm on the top level send block which will confirm everything underneath on both accounts. { - auto block = node->store.block.get (node->store.tx_begin_read (), latest); + auto block = node->ledger.block (node->store.tx_begin_read (), latest); node->scheduler.manual.push (block); std::shared_ptr election; ASSERT_TIMELY (10s, (election = node->active.election (block->qualified_root ())) != nullptr); diff --git a/nano/slow_test/vote_cache.cpp b/nano/slow_test/vote_cache.cpp index 05b5b66ed7..1e0b4abae8 100644 --- a/nano/slow_test/vote_cache.cpp +++ b/nano/slow_test/vote_cache.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -26,7 +27,7 @@ nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::u .balance (balance - amount) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto open = builder .open () @@ -35,7 +36,7 @@ nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::u .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); EXPECT_TRUE (nano::test::process (node, { send, open })); EXPECT_TRUE (nano::test::start_elections (system, node, { send, open }, true)); @@ -81,7 +82,7 @@ std::vector> setup_blocks (nano::test::system & sys .balance (balance) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto open = builder .open () @@ -90,7 +91,7 @@ std::vector> setup_blocks (nano::test::system & sys .account (key.pub) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); latest = send->hash (); diff --git a/nano/slow_test/vote_processor.cpp b/nano/slow_test/vote_processor.cpp index eaae35577d..4dc3c09992 100644 --- a/nano/slow_test/vote_processor.cpp +++ b/nano/slow_test/vote_processor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -75,5 +76,5 @@ TEST (vote_processor, producer_consumer) consumer_thread.join (); monitor_thread.join (); - ASSERT_TRUE (producer_wins > consumer_wins); + ASSERT_GT (producer_wins, consumer_wins); } diff --git a/nano/store/CMakeLists.txt b/nano/store/CMakeLists.txt index 427e038082..bf79b03e34 100644 --- a/nano/store/CMakeLists.txt +++ b/nano/store/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( component.hpp confirmation_height.hpp db_val.hpp + db_val_impl.hpp iterator.hpp iterator_impl.hpp final.hpp @@ -97,11 +98,10 @@ add_library( target_link_libraries( nano_store + nano_lib Boost::circular_buffer Boost::endian Boost::iostreams - Boost::log_setup - Boost::log Boost::multiprecision Boost::pool Boost::stacktrace diff --git a/nano/store/account.hpp b/nano/store/account.hpp index 9d20fdd384..749cd9c842 100644 --- a/nano/store/account.hpp +++ b/nano/store/account.hpp @@ -2,12 +2,14 @@ #include #include +#include #include #include namespace nano { +class account_info; class block_hash; } namespace nano::store diff --git a/nano/store/block.hpp b/nano/store/block.hpp index 826aafc41c..ad1fd55916 100644 --- a/nano/store/block.hpp +++ b/nano/store/block.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -9,6 +9,7 @@ namespace nano { +class block; class block_hash; } namespace nano::store diff --git a/nano/store/component.cpp b/nano/store/component.cpp index cd68dc2a09..838a7b9cb7 100644 --- a/nano/store/component.cpp +++ b/nano/store/component.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include diff --git a/nano/store/db_val.hpp b/nano/store/db_val.hpp index 957492e23e..fee58d9e0d 100644 --- a/nano/store/db_val.hpp +++ b/nano/store/db_val.hpp @@ -9,6 +9,14 @@ #include +namespace nano +{ +class account_info; +class block; +class pending_info; +class pending_key; +} + namespace nano::store { /** @@ -53,22 +61,11 @@ class db_val { } - db_val (nano::account_info const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) - { - } + db_val (nano::account_info const & val_a); - db_val (nano::pending_info const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) - { - static_assert (std::is_standard_layout::value, "Standard layout is required"); - } + db_val (nano::pending_info const & val_a); - db_val (nano::pending_key const & val_a) : - db_val (sizeof (val_a), const_cast (&val_a)) - { - static_assert (std::is_standard_layout::value, "Standard layout is required"); - } + db_val (nano::pending_key const & val_a); db_val (nano::confirmation_height_info const & val_a) : buffer (std::make_shared> ()) @@ -92,15 +89,7 @@ class db_val static_assert (std::is_standard_layout::value, "Standard layout is required"); } - db_val (std::shared_ptr const & val_a) : - buffer (std::make_shared> ()) - { - { - nano::vectorstream stream (*buffer); - nano::serialize_block (stream, *val_a); - } - convert_buffer_to_value (); - } + db_val (std::shared_ptr const & val_a); db_val (uint64_t val_a) : buffer (std::make_shared> ()) @@ -113,13 +102,7 @@ class db_val convert_buffer_to_value (); } - explicit operator nano::account_info () const - { - nano::account_info result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; - } + explicit operator nano::account_info () const; explicit operator block_info () const { @@ -130,22 +113,9 @@ class db_val return result; } - explicit operator nano::pending_info () const - { - nano::pending_info result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; - } + explicit operator nano::pending_info () const; - explicit operator nano::pending_key () const - { - nano::pending_key result; - debug_assert (size () == sizeof (result)); - static_assert (sizeof (nano::pending_key::account) + sizeof (nano::pending_key::hash) == sizeof (result), "Packed class"); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + sizeof (result), reinterpret_cast (&result)); - return result; - } + explicit operator nano::pending_key () const; explicit operator nano::confirmation_height_info () const { @@ -209,16 +179,7 @@ class db_val return result; } - explicit operator block_w_sideband () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - nano::store::block_w_sideband block_w_sideband; - block_w_sideband.block = (nano::deserialize_block (stream)); - auto error = block_w_sideband.sideband.deserialize (stream, block_w_sideband.block->type ()); - release_assert (!error); - block_w_sideband.block->sideband_set (block_w_sideband.sideband); - return block_w_sideband; - } + explicit operator block_w_sideband () const; explicit operator std::nullptr_t () const { @@ -230,12 +191,7 @@ class db_val return no_value::dummy; } - explicit operator std::shared_ptr () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - std::shared_ptr result (nano::deserialize_block (stream)); - return result; - } + explicit operator std::shared_ptr () const; template std::shared_ptr convert_to_block () const diff --git a/nano/store/db_val_impl.hpp b/nano/store/db_val_impl.hpp new file mode 100644 index 0000000000..c8ee18624f --- /dev/null +++ b/nano/store/db_val_impl.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include + +template +nano::store::db_val::db_val (nano::account_info const & val_a) : + db_val (val_a.db_size (), const_cast (&val_a)) +{ +} +template +nano::store::db_val::db_val (std::shared_ptr const & val_a) : + buffer (std::make_shared> ()) +{ + { + nano::vectorstream stream (*buffer); + nano::serialize_block (stream, *val_a); + } + convert_buffer_to_value (); +} + +template +nano::store::db_val::db_val (nano::pending_info const & val_a) : + db_val (val_a.db_size (), const_cast (&val_a)) +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +template +nano::store::db_val::db_val (nano::pending_key const & val_a) : + db_val (sizeof (val_a), const_cast (&val_a)) +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +template +nano::store::db_val::operator nano::account_info () const +{ + nano::account_info result; + debug_assert (size () == result.db_size ()); + std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); + return result; +} + +template +nano::store::db_val::operator std::shared_ptr () const +{ + nano::bufferstream stream (reinterpret_cast (data ()), size ()); + std::shared_ptr result (nano::deserialize_block (stream)); + return result; +} + +template +nano::store::db_val::operator nano::store::block_w_sideband () const +{ + nano::bufferstream stream (reinterpret_cast (data ()), size ()); + nano::store::block_w_sideband block_w_sideband; + block_w_sideband.block = (nano::deserialize_block (stream)); + auto error = block_w_sideband.sideband.deserialize (stream, block_w_sideband.block->type ()); + release_assert (!error); + block_w_sideband.block->sideband_set (block_w_sideband.sideband); + return block_w_sideband; +} + +template +nano::store::db_val::operator nano::pending_info () const +{ + nano::pending_info result; + debug_assert (size () == result.db_size ()); + std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); + return result; +} + +template +nano::store::db_val::operator nano::pending_key () const +{ + nano::pending_key result; + debug_assert (size () == sizeof (result)); + static_assert (sizeof (nano::pending_key::account) + sizeof (nano::pending_key::hash) == sizeof (result), "Packed class"); + std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + sizeof (result), reinterpret_cast (&result)); + return result; +} diff --git a/nano/store/iterator.hpp b/nano/store/iterator.hpp index 00f2ab7f93..aef5cc709f 100644 --- a/nano/store/iterator.hpp +++ b/nano/store/iterator.hpp @@ -45,7 +45,7 @@ class iterator final return *this; } iterator & operator= (iterator const &) = delete; - std::pair * operator-> () + std::pair * operator->() { return ¤t; } diff --git a/nano/store/lmdb/account.hpp b/nano/store/lmdb/account.hpp index 9c3284b482..6faaf3cfe8 100644 --- a/nano/store/lmdb/account.hpp +++ b/nano/store/lmdb/account.hpp @@ -29,27 +29,27 @@ class account : public nano::store::account void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Maps account v1 to account information, head, rep, open, balance, timestamp and block count. (Removed) - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t - */ + * Maps account v1 to account information, head, rep, open, balance, timestamp and block count. (Removed) + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t + */ MDB_dbi accounts_v0_handle{ 0 }; /** - * Maps account v0 to account information, head, rep, open, balance, timestamp and block count. (Removed) - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t - */ + * Maps account v0 to account information, head, rep, open, balance, timestamp and block count. (Removed) + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t + */ MDB_dbi accounts_v1_handle{ 0 }; /** - * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch - */ + * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch + */ MDB_dbi accounts_handle{ 0 }; /** - * Representative weights. (Removed) - * nano::account -> nano::uint128_t - */ + * Representative weights. (Removed) + * nano::account -> nano::uint128_t + */ MDB_dbi representation_handle{ 0 }; }; } // amespace nano::store::lmdb diff --git a/nano/store/lmdb/block.cpp b/nano/store/lmdb/block.cpp index ff6113f089..38e695ba66 100644 --- a/nano/store/lmdb/block.cpp +++ b/nano/store/lmdb/block.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/nano/store/lmdb/block.hpp b/nano/store/lmdb/block.hpp index a16f213859..b9ccc3b475 100644 --- a/nano/store/lmdb/block.hpp +++ b/nano/store/lmdb/block.hpp @@ -37,9 +37,9 @@ class block : public nano::store::block void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Contains block_sideband and block for all block types (legacy send/change/open/receive & state blocks) - * nano::block_hash -> nano::block_sideband, nano::block - */ + * Contains block_sideband and block for all block types (legacy send/change/open/receive & state blocks) + * nano::block_hash -> nano::block_sideband, nano::block + */ MDB_dbi blocks_handle{ 0 }; protected: diff --git a/nano/store/lmdb/confirmation_height.hpp b/nano/store/lmdb/confirmation_height.hpp index 738c8482c6..4674f81137 100644 --- a/nano/store/lmdb/confirmation_height.hpp +++ b/nano/store/lmdb/confirmation_height.hpp @@ -29,9 +29,9 @@ class confirmation_height : public nano::store::confirmation_height void for_each_par (std::function, store::iterator)> const & action_a) const override; /* - * Confirmation height of an account, and the hash for the block at that height - * nano::account -> uint64_t, nano::block_hash - */ + * Confirmation height of an account, and the hash for the block at that height + * nano::account -> uint64_t, nano::block_hash + */ MDB_dbi confirmation_height_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/final_vote.hpp b/nano/store/lmdb/final_vote.hpp index b7c06c62fd..92fc5253fd 100644 --- a/nano/store/lmdb/final_vote.hpp +++ b/nano/store/lmdb/final_vote.hpp @@ -29,9 +29,9 @@ class final_vote : public nano::store::final_vote void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Maps root to block hash for generated final votes. - * nano::qualified_root -> nano::block_hash - */ + * Maps root to block hash for generated final votes. + * nano::qualified_root -> nano::block_hash + */ MDB_dbi final_votes_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/frontier.hpp b/nano/store/lmdb/frontier.hpp index 6bf71068bf..95205d4cd0 100644 --- a/nano/store/lmdb/frontier.hpp +++ b/nano/store/lmdb/frontier.hpp @@ -26,9 +26,9 @@ class frontier : public nano::store::frontier void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Maps head block to owning account - * nano::block_hash -> nano::account - */ + * Maps head block to owning account + * nano::block_hash -> nano::account + */ MDB_dbi frontiers_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/iterator.hpp b/nano/store/lmdb/iterator.hpp index e8230fd73f..ff7cb0977c 100644 --- a/nano/store/lmdb/iterator.hpp +++ b/nano/store/lmdb/iterator.hpp @@ -95,7 +95,7 @@ class iterator : public iterator_impl return *this; } - std::pair, store::db_val> * operator-> () + std::pair, store::db_val> * operator->() { return ¤t; } @@ -213,9 +213,9 @@ class merge_iterator : public iterator_impl return *this; } - std::pair, store::db_val> * operator-> () + std::pair, store::db_val> * operator->() { - return least_iterator ().operator-> (); + return least_iterator ().operator->(); } bool operator== (merge_iterator const & other) const diff --git a/nano/store/lmdb/lmdb.cpp b/nano/store/lmdb/lmdb.cpp index 8834c38d01..4dd9e64407 100644 --- a/nano/store/lmdb/lmdb.cpp +++ b/nano/store/lmdb/lmdb.cpp @@ -12,7 +12,7 @@ #include -nano::store::lmdb::component::component (nano::logger_mt & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade_a) : +nano::store::lmdb::component::component (nano::logger & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade_a) : // clang-format off nano::store::component{ block_store, @@ -37,7 +37,7 @@ nano::store::lmdb::component::component (nano::logger_mt & logger_a, std::filesy confirmation_height_store{ *this }, final_vote_store{ *this }, version_store{ *this }, - logger (logger_a), + logger{ logger_a }, env (error, path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).set_use_no_mem_init (true)), mdb_txn_tracker (logger_a, txn_tracking_config_a, block_processor_batch_max_time_a), txn_tracking_enabled (txn_tracking_config_a.enable) @@ -66,10 +66,11 @@ nano::store::lmdb::component::component (nano::logger_mt & logger_a, std::filesy { if (!is_fresh_db) { - logger.always_log ("Upgrade in progress..."); + logger.info (nano::log::type::lmdb, "Upgrade in progress..."); + if (backup_before_upgrade_a) { - create_backup_file (env, path_a, logger_a); + create_backup_file (env, path_a, logger); } } auto needs_vacuuming = false; @@ -84,9 +85,18 @@ nano::store::lmdb::component::component (nano::logger_mt & logger_a, std::filesy if (needs_vacuuming) { - logger.always_log ("Preparing vacuum..."); + logger.info (nano::log::type::lmdb, "Ledger vaccum in progress..."); + auto vacuum_success = vacuum_after_upgrade (path_a, lmdb_config_a); - logger.always_log (vacuum_success ? "Vacuum succeeded." : "Failed to vacuum. (Optional) Ensure enough disk space is available for a copy of the database and try to vacuum after shutting down the node"); + if (vacuum_success) + { + logger.info (nano::log::type::lmdb, "Ledger vacuum completed"); + } + else + { + logger.error (nano::log::type::lmdb, "Ledger vaccum failed"); + logger.error (nano::log::type::lmdb, "(Optional) Please ensure enough disk space is available for a copy of the database and try to vacuum after shutting down the node"); + } } } else @@ -202,7 +212,7 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans auto version_l = version.get (transaction_a); if (version_l < version_minimum) { - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is lower than the minimum (%2%) which is supported for upgrades. Either upgrade to a v19, v20 or v21 node first or delete the ledger.") % version_l % version_minimum)); + logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is lower than the minimum ({}) which is supported for upgrades. Either upgrade a node first or delete the ledger.", version_l, version_minimum); return true; } switch (version_l) @@ -213,7 +223,7 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans case 22: break; default: - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is too high for this node") % version_l)); + logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is too high for this node", version_l); error = true; break; } @@ -222,16 +232,18 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans void nano::store::lmdb::component::upgrade_v21_to_v22 (store::write_transaction const & transaction_a) { - logger.always_log ("Preparing v21 to v22 database upgrade..."); + logger.info (nano::log::type::lmdb, "Upgrading database from v21 to v22..."); + MDB_dbi unchecked_handle{ 0 }; release_assert (!mdb_dbi_open (env.tx (transaction_a), "unchecked", MDB_CREATE, &unchecked_handle)); release_assert (!mdb_drop (env.tx (transaction_a), unchecked_handle, 1)); // del = 1, to delete it from the environment and close the DB handle. version.put (transaction_a, 22); - logger.always_log ("Finished removing unchecked table"); + + logger.info (nano::log::type::lmdb, "Upgrading database from v21 to v22 completed"); } /** Takes a filepath, appends '_backup_' to the end (but before any extension) and saves that file in the same directory */ -void nano::store::lmdb::component::create_backup_file (nano::store::lmdb::env & env_a, std::filesystem::path const & filepath_a, nano::logger_mt & logger_a) +void nano::store::lmdb::component::create_backup_file (nano::store::lmdb::env & env_a, std::filesystem::path const & filepath_a, nano::logger & logger) { auto extension = filepath_a.extension (); auto filename_without_extension = filepath_a.filename ().replace_extension (""); @@ -242,22 +254,18 @@ void nano::store::lmdb::component::create_backup_file (nano::store::lmdb::env & backup_filename += std::to_string (std::chrono::system_clock::now ().time_since_epoch ().count ()); backup_filename += extension; auto backup_filepath = backup_path / backup_filename; - auto start_message (boost::str (boost::format ("Performing %1% backup before database upgrade...") % filepath_a.filename ())); - logger_a.always_log (start_message); - std::cout << start_message << std::endl; + + logger.info (nano::log::type::lmdb, "Performing {} backup before database upgrade...", filepath_a.filename ().string ()); + auto error (mdb_env_copy (env_a, backup_filepath.string ().c_str ())); if (error) { - auto error_message (boost::str (boost::format ("%1% backup failed") % filepath_a.filename ())); - logger_a.always_log (error_message); - std::cerr << error_message << std::endl; + logger.critical (nano::log::type::lmdb, "Database backup failed"); std::exit (1); } else { - auto success_message (boost::str (boost::format ("Backup created: %1%") % backup_filename)); - logger_a.always_log (success_message); - std::cout << success_message << std::endl; + logger.info (nano::log::type::lmdb, "Database backup completed. Backup can be found at: {}", backup_filepath.string ()); } } diff --git a/nano/store/lmdb/lmdb.hpp b/nano/store/lmdb/lmdb.hpp index 91822f7f95..a1f5dda6cf 100644 --- a/nano/store/lmdb/lmdb.hpp +++ b/nano/store/lmdb/lmdb.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include @@ -63,7 +63,7 @@ class component : public nano::store::component friend class nano::store::lmdb::version; public: - component (nano::logger_mt &, std::filesystem::path const &, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false); + component (nano::logger &, std::filesystem::path const &, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false); store::write_transaction tx_begin_write (std::vector const & tables_requiring_lock = {}, std::vector const & tables_no_lock = {}) override; store::read_transaction tx_begin_read () const override; @@ -71,14 +71,14 @@ class component : public nano::store::component void serialize_mdb_tracker (boost::property_tree::ptree &, std::chrono::milliseconds, std::chrono::milliseconds) override; - static void create_backup_file (nano::store::lmdb::env &, std::filesystem::path const &, nano::logger_mt &); + static void create_backup_file (nano::store::lmdb::env &, std::filesystem::path const &, nano::logger &); void serialize_memory_stats (boost::property_tree::ptree &) override; unsigned max_block_write_batch_num () const override; private: - nano::logger_mt & logger; + nano::logger & logger; bool error{ false }; public: diff --git a/nano/store/lmdb/lmdb_env.cpp b/nano/store/lmdb/lmdb_env.cpp index 9e627c7676..cd1897c80a 100644 --- a/nano/store/lmdb/lmdb_env.cpp +++ b/nano/store/lmdb/lmdb_env.cpp @@ -1,6 +1,8 @@ #include #include +#include + nano::store::lmdb::env::env (bool & error_a, std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a) { init (error_a, path_a, options_a); @@ -8,6 +10,8 @@ nano::store::lmdb::env::env (bool & error_a, std::filesystem::path const & path_ void nano::store::lmdb::env::init (bool & error_a, std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a) { + debug_assert (path_a.extension () == ".ldb", "invalid filename extension for lmdb database file"); + boost::system::error_code error_mkdir, error_chmod; if (path_a.has_parent_path ()) { diff --git a/nano/store/lmdb/lmdb_env.hpp b/nano/store/lmdb/lmdb_env.hpp index f947077c6b..e912653250 100644 --- a/nano/store/lmdb/lmdb_env.hpp +++ b/nano/store/lmdb/lmdb_env.hpp @@ -5,11 +5,6 @@ #include #include -namespace -{ -nano::id_dispenser id_gen; -} - namespace nano::store::lmdb { /** @@ -68,6 +63,6 @@ class env final store::write_transaction tx_begin_write (txn_callbacks callbacks = txn_callbacks{}) const; MDB_txn * tx (store::transaction const & transaction_a) const; MDB_env * environment; - nano::id_dispenser::id_t const store_id{ id_gen.next_id () }; + nano::id_t const store_id{ nano::next_id () }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/online_weight.hpp b/nano/store/lmdb/online_weight.hpp index df70dfb9d0..0567c63d9b 100644 --- a/nano/store/lmdb/online_weight.hpp +++ b/nano/store/lmdb/online_weight.hpp @@ -22,9 +22,9 @@ class online_weight : public nano::store::online_weight void clear (store::write_transaction const & transaction_a) override; /** - * Samples of online vote weight - * uint64_t -> nano::amount - */ + * Samples of online vote weight + * uint64_t -> nano::amount + */ MDB_dbi online_weight_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/peer.hpp b/nano/store/lmdb/peer.hpp index 7519908eee..13ae1b59f3 100644 --- a/nano/store/lmdb/peer.hpp +++ b/nano/store/lmdb/peer.hpp @@ -22,9 +22,9 @@ class peer : public nano::store::peer store::iterator end () const override; /* - * Endpoints for peers - * nano::endpoint_key -> no_value - */ + * Endpoints for peers + * nano::endpoint_key -> no_value + */ MDB_dbi peers_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/pending.cpp b/nano/store/lmdb/pending.cpp index 961b201829..cabb70896b 100644 --- a/nano/store/lmdb/pending.cpp +++ b/nano/store/lmdb/pending.cpp @@ -17,16 +17,18 @@ void nano::store::lmdb::pending::del (store::write_transaction const & transacti store.release_assert_success (status); } -bool nano::store::lmdb::pending::get (store::transaction const & transaction, nano::pending_key const & key, nano::pending_info & pending_a) +std::optional nano::store::lmdb::pending::get (store::transaction const & transaction, nano::pending_key const & key) { nano::store::lmdb::db_val value; auto status1 = store.get (transaction, tables::pending, key, value); release_assert (store.success (status1) || store.not_found (status1)); - bool result (true); + std::optional result; if (store.success (status1)) { nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); - result = pending_a.deserialize (stream); + result = nano::pending_info{}; + auto error = result.value ().deserialize (stream); + release_assert (!error); } return result; } diff --git a/nano/store/lmdb/pending.hpp b/nano/store/lmdb/pending.hpp index 7b39a9132c..13cd9172d2 100644 --- a/nano/store/lmdb/pending.hpp +++ b/nano/store/lmdb/pending.hpp @@ -19,7 +19,7 @@ class pending : public nano::store::pending explicit pending (nano::store::lmdb::component & store_a); void put (store::write_transaction const & transaction_a, nano::pending_key const & key_a, nano::pending_info const & pending_info_a) override; void del (store::write_transaction const & transaction_a, nano::pending_key const & key_a) override; - bool get (store::transaction const & transaction_a, nano::pending_key const & key_a, nano::pending_info & pending_a) override; + std::optional get (store::transaction const & transaction_a, nano::pending_key const & key_a) override; bool exists (store::transaction const & transaction_a, nano::pending_key const & key_a) override; bool any (store::transaction const & transaction_a, nano::account const & account_a) override; store::iterator begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const override; @@ -28,21 +28,21 @@ class pending : public nano::store::pending void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Maps min_version 0 (destination account, pending block) to (source account, amount). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount - */ + * Maps min_version 0 (destination account, pending block) to (source account, amount). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount + */ MDB_dbi pending_v0_handle{ 0 }; /** - * Maps min_version 1 (destination account, pending block) to (source account, amount). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount - */ + * Maps min_version 1 (destination account, pending block) to (source account, amount). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount + */ MDB_dbi pending_v1_handle{ 0 }; /** - * Maps (destination account, pending block) to (source account, amount, version). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount, nano::epoch - */ + * Maps (destination account, pending block) to (source account, amount, version). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount, nano::epoch + */ MDB_dbi pending_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/pruned.hpp b/nano/store/lmdb/pruned.hpp index d0c3c5d075..0aa2d7fc20 100644 --- a/nano/store/lmdb/pruned.hpp +++ b/nano/store/lmdb/pruned.hpp @@ -25,9 +25,9 @@ class pruned : public nano::store::pruned void for_each_par (std::function, store::iterator)> const & action_a) const override; /** - * Pruned blocks hashes - * nano::block_hash -> none - */ + * Pruned blocks hashes + * nano::block_hash -> none + */ MDB_dbi pruned_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/lmdb/transaction.cpp b/nano/store/lmdb/transaction.cpp index a01698c09d..2460539cfb 100644 --- a/nano/store/lmdb/transaction.cpp +++ b/nano/store/lmdb/transaction.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -116,7 +116,7 @@ bool nano::store::lmdb::write_transaction_impl::contains (nano::tables table_a) return true; } -nano::mdb_txn_tracker::mdb_txn_tracker (nano::logger_mt & logger_a, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a) : +nano::mdb_txn_tracker::mdb_txn_tracker (nano::logger & logger_a, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a) : logger (logger_a), txn_tracking_config (txn_tracking_config_a), block_processor_batch_max_time (block_processor_batch_max_time_a) @@ -194,7 +194,12 @@ void nano::mdb_txn_tracker::log_if_held_long_enough (nano::mdb_txn_stats const & if (!should_ignore && ((is_write && time_open >= txn_tracking_config.min_write_txn_time) || (!is_write && time_open >= txn_tracking_config.min_read_txn_time))) { debug_assert (mdb_txn_stats.stacktrace); - logger.always_log (boost::str (boost::format ("%1%ms %2% held on thread %3%\n%4%") % mdb_txn_stats.timer.since_start ().count () % (is_write ? "write lock" : "read") % mdb_txn_stats.thread_name % *mdb_txn_stats.stacktrace)); + + logger.warn (nano::log::type::txn_tracker, "{}ms {} held on thread {}\n{}", + time_open.count (), + is_write ? "write lock" : "read", + mdb_txn_stats.thread_name, + nano::util::to_str (*mdb_txn_stats.stacktrace)); } } diff --git a/nano/store/lmdb/transaction_impl.hpp b/nano/store/lmdb/transaction_impl.hpp index 001fd896a3..06a4e1d414 100644 --- a/nano/store/lmdb/transaction_impl.hpp +++ b/nano/store/lmdb/transaction_impl.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -11,10 +12,6 @@ #include -namespace nano -{ -class logger_mt; -} namespace nano::store::lmdb { class env; @@ -75,7 +72,7 @@ class mdb_txn_stats class mdb_txn_tracker { public: - mdb_txn_tracker (nano::logger_mt & logger_a, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a); + mdb_txn_tracker (nano::logger &, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a); void serialize_json (boost::property_tree::ptree & json, std::chrono::milliseconds min_read_time, std::chrono::milliseconds min_write_time); void add (store::transaction_impl const * transaction_impl); void erase (store::transaction_impl const * transaction_impl); @@ -83,7 +80,7 @@ class mdb_txn_tracker private: nano::mutex mutex; std::vector stats; - nano::logger_mt & logger; + nano::logger & logger; nano::txn_tracking_config txn_tracking_config; std::chrono::milliseconds block_processor_batch_max_time; diff --git a/nano/store/lmdb/version.hpp b/nano/store/lmdb/version.hpp index fa9cb04298..7ec10b8183 100644 --- a/nano/store/lmdb/version.hpp +++ b/nano/store/lmdb/version.hpp @@ -17,9 +17,9 @@ class version : public nano::store::version int get (store::transaction const & transaction_a) const override; /** - * Meta information about block store, such as versions. - * nano::uint256_union (arbitrary key) -> blob - */ + * Meta information about block store, such as versions. + * nano::uint256_union (arbitrary key) -> blob + */ MDB_dbi meta_handle{ 0 }; }; } // namespace nano::store::lmdb diff --git a/nano/store/pending.hpp b/nano/store/pending.hpp index 6c5b379323..49f2b8a31c 100644 --- a/nano/store/pending.hpp +++ b/nano/store/pending.hpp @@ -5,10 +5,13 @@ #include #include +#include namespace nano { class block_hash; +class pending_info; +class pending_key; } namespace nano::store { @@ -20,7 +23,7 @@ class pending public: virtual void put (store::write_transaction const &, nano::pending_key const &, nano::pending_info const &) = 0; virtual void del (store::write_transaction const &, nano::pending_key const &) = 0; - virtual bool get (store::transaction const &, nano::pending_key const &, nano::pending_info &) = 0; + virtual std::optional get (store::transaction const &, nano::pending_key const &) = 0; virtual bool exists (store::transaction const &, nano::pending_key const &) = 0; virtual bool any (store::transaction const &, nano::account const &) = 0; virtual store::iterator begin (store::transaction const &, nano::pending_key const &) const = 0; diff --git a/nano/store/rocksdb/block.cpp b/nano/store/rocksdb/block.cpp index 2fe5365e86..a910e0cc73 100644 --- a/nano/store/rocksdb/block.cpp +++ b/nano/store/rocksdb/block.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/nano/store/rocksdb/iterator.hpp b/nano/store/rocksdb/iterator.hpp index 0351367828..ec4865e526 100644 --- a/nano/store/rocksdb/iterator.hpp +++ b/nano/store/rocksdb/iterator.hpp @@ -129,7 +129,7 @@ class iterator : public iterator_impl return *this; } - std::pair * operator-> () + std::pair * operator->() { return ¤t; } diff --git a/nano/store/rocksdb/pending.cpp b/nano/store/rocksdb/pending.cpp index f7e843f184..27efe5e637 100644 --- a/nano/store/rocksdb/pending.cpp +++ b/nano/store/rocksdb/pending.cpp @@ -17,16 +17,18 @@ void nano::store::rocksdb::pending::del (store::write_transaction const & transa store.release_assert_success (status); } -bool nano::store::rocksdb::pending::get (store::transaction const & transaction, nano::pending_key const & key, nano::pending_info & pending) +std::optional nano::store::rocksdb::pending::get (store::transaction const & transaction, nano::pending_key const & key) { nano::store::rocksdb::db_val value; auto status1 = store.get (transaction, tables::pending, key, value); release_assert (store.success (status1) || store.not_found (status1)); - bool result (true); + std::optional result; if (store.success (status1)) { nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); - result = pending.deserialize (stream); + result = nano::pending_info{}; + auto error = result.value ().deserialize (stream); + release_assert (!error); } return result; } diff --git a/nano/store/rocksdb/pending.hpp b/nano/store/rocksdb/pending.hpp index 76a5f67d6d..0ee4ced54a 100644 --- a/nano/store/rocksdb/pending.hpp +++ b/nano/store/rocksdb/pending.hpp @@ -13,7 +13,7 @@ class pending : public nano::store::pending explicit pending (nano::store::rocksdb::component & store_a); void put (store::write_transaction const & transaction_a, nano::pending_key const & key_a, nano::pending_info const & pending_info_a) override; void del (store::write_transaction const & transaction_a, nano::pending_key const & key_a) override; - bool get (store::transaction const & transaction_a, nano::pending_key const & key_a, nano::pending_info & pending_a) override; + std::optional get (store::transaction const & transaction_a, nano::pending_key const & key_a) override; bool exists (store::transaction const & transaction_a, nano::pending_key const & key_a) override; bool any (store::transaction const & transaction_a, nano::account const & account_a) override; store::iterator begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const override; diff --git a/nano/store/rocksdb/rocksdb.cpp b/nano/store/rocksdb/rocksdb.cpp index 054fec0a82..43b82f2b4c 100644 --- a/nano/store/rocksdb/rocksdb.cpp +++ b/nano/store/rocksdb/rocksdb.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -34,7 +35,7 @@ class event_listener : public rocksdb::EventListener }; } -nano::store::rocksdb::component::component (nano::logger_mt & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::rocksdb_config const & rocksdb_config_a, bool open_read_only_a) : +nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::rocksdb_config const & rocksdb_config_a, bool open_read_only_a) : // clang-format off nano::store::component{ block_store, @@ -95,14 +96,16 @@ nano::store::rocksdb::component::component (nano::logger_mt & logger_a, std::fil auto version_l = version.get (transaction); if (version_l > version_current) { + logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is too high for this node", version_l); + error = true; - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is too high for this node") % version_l)); return; } else if (version_l < version_minimum) { + logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is lower than the minimum ({}) which is supported for upgrades. Either upgrade a node first or delete the ledger.", version_l, version_minimum); + error = true; - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is lower than the minimum (%2%) which is supported for upgrades. Either upgrade to a v19, v20 or v21 node first or delete the ledger.") % version_l % version_minimum)); return; } is_fully_upgraded = (version_l == version_current); @@ -149,7 +152,8 @@ nano::store::rocksdb::component::component (nano::logger_mt & logger_a, std::fil open (error, path_a, open_read_only_a, options, get_current_column_families (path_a.string (), options)); if (!error) { - logger.always_log ("Upgrade in progress..."); + logger.info (nano::log::type::rocksdb, "Upgrade in progress..."); + auto transaction = tx_begin_write (); error |= do_upgrades (transaction); } @@ -240,7 +244,7 @@ bool nano::store::rocksdb::component::do_upgrades (store::write_transaction cons case 22: break; default: - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is too high for this node") % version_l)); + logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is too high for this node", version_l); error_l = true; break; } @@ -249,7 +253,8 @@ bool nano::store::rocksdb::component::do_upgrades (store::write_transaction cons void nano::store::rocksdb::component::upgrade_v21_to_v22 (store::write_transaction const & transaction_a) { - logger.always_log ("Preparing v21 to v22 database upgrade..."); + logger.info (nano::log::type::rocksdb, "Upgrading database from v21 to v22..."); + if (column_family_exists ("unchecked")) { auto const unchecked_handle = get_column_family ("unchecked"); @@ -264,9 +269,12 @@ void nano::store::rocksdb::component::upgrade_v21_to_v22 (store::write_transacti } return false; }); + logger.debug (nano::log::type::rocksdb, "Finished removing unchecked table"); } + version.put (transaction_a, 22); - logger.always_log ("Finished removing unchecked table"); + + logger.info (nano::log::type::rocksdb, "Upgrading database from v21 to v22 completed"); } void nano::store::rocksdb::component::generate_tombstone_map () diff --git a/nano/store/rocksdb/rocksdb.hpp b/nano/store/rocksdb/rocksdb.hpp index 9490ed9522..1c51bbbb05 100644 --- a/nano/store/rocksdb/rocksdb.hpp +++ b/nano/store/rocksdb/rocksdb.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -36,8 +36,8 @@ namespace nano::store::rocksdb class rocksdb_block_store_upgrade_v21_v22_Test; /** - * rocksdb implementation of the block store - */ + * rocksdb implementation of the block store + */ class component : public nano::store::component { private: @@ -64,7 +64,7 @@ class component : public nano::store::component friend class nano::store::rocksdb::pruned; friend class nano::store::rocksdb::version; - explicit component (nano::logger_mt &, std::filesystem::path const &, nano::ledger_constants & constants, nano::rocksdb_config const & = nano::rocksdb_config{}, bool open_read_only = false); + explicit component (nano::logger &, std::filesystem::path const &, nano::ledger_constants & constants, nano::rocksdb_config const & = nano::rocksdb_config{}, bool open_read_only = false); store::write_transaction tx_begin_write (std::vector const & tables_requiring_lock = {}, std::vector const & tables_no_lock = {}) override; store::read_transaction tx_begin_read () const override; @@ -103,7 +103,7 @@ class component : public nano::store::component private: bool error{ false }; - nano::logger_mt & logger; + nano::logger & logger; nano::ledger_constants & constants; // Optimistic transactions are used in write mode ::rocksdb::OptimisticTransactionDB * optimistic_db = nullptr; diff --git a/nano/store/versioning.hpp b/nano/store/versioning.hpp index 0160535345..b165eef7dc 100644 --- a/nano/store/versioning.hpp +++ b/nano/store/versioning.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include struct MDB_val; diff --git a/nano/test_common/CMakeLists.txt b/nano/test_common/CMakeLists.txt index 337d34211d..6271377f45 100644 --- a/nano/test_common/CMakeLists.txt +++ b/nano/test_common/CMakeLists.txt @@ -15,7 +15,7 @@ add_library( testutil.hpp testutil.cpp) -target_link_libraries(test_common node gtest Boost::log_setup Boost::log) +target_link_libraries(test_common node gtest) include_directories(${CMAKE_SOURCE_DIR}/submodules) include_directories(${CMAKE_SOURCE_DIR}/submodules/gtest/googletest/include) diff --git a/nano/test_common/chains.cpp b/nano/test_common/chains.cpp index dc6123792a..9bc2fa99ed 100644 --- a/nano/test_common/chains.cpp +++ b/nano/test_common/chains.cpp @@ -1,3 +1,4 @@ +#include #include using namespace std::chrono_literals; @@ -23,7 +24,7 @@ nano::block_list_t nano::test::setup_chain (nano::test::system & system, nano::n .link (throwaway.pub) .sign (target.prv, target.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); latest = send->hash (); @@ -63,7 +64,7 @@ std::vector> nano::test::setup_chai .link (key.pub) .sign (source.prv, source.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto open = builder .state () @@ -74,7 +75,7 @@ std::vector> nano::test::setup_chai .link (send->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); latest = send->hash (); @@ -120,7 +121,7 @@ nano::block_list_t nano::test::setup_independent_blocks (nano::test::system & sy .link (key.pub) .sign (source.prv, source.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); latest = send->hash (); @@ -133,7 +134,7 @@ nano::block_list_t nano::test::setup_independent_blocks (nano::test::system & sy .link (send->hash ()) .sign (key.prv, key.pub) .work (*system.work.generate (key.pub)) - .build_shared (); + .build (); EXPECT_TRUE (nano::test::process (node, { send, open })); EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger @@ -162,7 +163,7 @@ std::pair, std::shared_ptr> nano::test .link (dest.pub) .sign (source.prv, source.pub) .work (*system.work.generate (latest)) - .build_shared (); + .build (); auto open = nano::block_builder () .state () @@ -173,7 +174,7 @@ std::pair, std::shared_ptr> nano::test .link (send->hash ()) .sign (dest.prv, dest.pub) .work (*system.work.generate (dest.pub)) - .build_shared (); + .build (); EXPECT_TRUE (nano::test::process (node, { send, open })); EXPECT_TRUE (nano::test::start_elections (system, node, { send, open }, force_confirm)); diff --git a/nano/test_common/chains.hpp b/nano/test_common/chains.hpp index 2004159cac..f8fd4229df 100644 --- a/nano/test_common/chains.hpp +++ b/nano/test_common/chains.hpp @@ -8,6 +8,11 @@ #include #include +namespace nano +{ +using block_list_t = std::vector>; +} + /* * Helper functions to deal with common chain setup scenarios */ diff --git a/nano/test_common/ledger.cpp b/nano/test_common/ledger.cpp index a3337bc925..a4c91533d2 100644 --- a/nano/test_common/ledger.cpp +++ b/nano/test_common/ledger.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -12,8 +13,8 @@ nano::test::context::ledger_context::ledger_context (std::dequeinitialize (tx, ledger_m.cache, ledger_m.constants); for (auto const & i : blocks_m) { - auto process_result = ledger_m.process (tx, *i); - debug_assert (process_result.code == nano::process_result::progress); + auto process_result = ledger_m.process (tx, i); + debug_assert (process_result == nano::block_status::progress); } } @@ -56,7 +57,7 @@ auto nano::test::context::ledger_send_receive () -> ledger_context .link (nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); blocks.push_back (send); auto receive = builder.state () .make_block () @@ -67,7 +68,7 @@ auto nano::test::context::ledger_send_receive () -> ledger_context .link (send->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) - .build_shared (); + .build (); blocks.push_back (receive); return ledger_context{ std::move (blocks) }; } @@ -84,7 +85,7 @@ auto nano::test::context::ledger_send_receive_legacy () -> ledger_context .balance (nano::dev::constants.genesis_amount - 1) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (nano::dev::genesis->hash ())) - .build_shared (); + .build (); blocks.push_back (send); auto receive = builder.receive () .make_block () @@ -92,7 +93,7 @@ auto nano::test::context::ledger_send_receive_legacy () -> ledger_context .source (send->hash ()) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*pool.generate (send->hash ())) - .build_shared (); + .build (); blocks.push_back (receive); return ledger_context{ std::move (blocks) }; } diff --git a/nano/test_common/ledger.hpp b/nano/test_common/ledger.hpp index 6d64e170e4..6b12c258a2 100644 --- a/nano/test_common/ledger.hpp +++ b/nano/test_common/ledger.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -26,7 +25,7 @@ namespace test std::deque> const & blocks () const; private: - nano::logger_mt logger; + nano::logger logger; std::unique_ptr store_m; nano::stats stats_m; nano::ledger ledger_m; diff --git a/nano/test_common/network.cpp b/nano/test_common/network.cpp index 3241afca61..80ec2065c0 100644 --- a/nano/test_common/network.cpp +++ b/nano/test_common/network.cpp @@ -26,8 +26,33 @@ std::shared_ptr nano::test::establish_tcp (nano::t std::shared_ptr nano::test::add_outer_node (nano::test::system & system_a, nano::node_flags flags_a) { - auto outer_node = std::make_shared (system_a.io_ctx, system_a.get_available_port (), nano::unique_path (), system_a.logging, system_a.work, flags_a); + auto outer_node = std::make_shared (system_a.io_ctx, system_a.get_available_port (), nano::unique_path (), system_a.work, flags_a); outer_node->start (); system_a.nodes.push_back (outer_node); return outer_node; } + +// Note: this is not guaranteed to work, it is speculative +uint16_t nano::test::speculatively_choose_a_free_tcp_bind_port () +{ + /* + * This works because the kernel doesn't seem to reuse port numbers until it absolutely has to. + * Subsequent binds to port 0 will allocate a different port number. + */ + boost::asio::io_context io_ctx; + boost::asio::ip::tcp::acceptor acceptor{ io_ctx }; + boost::asio::ip::tcp::tcp::endpoint endpoint{ boost::asio::ip::tcp::v4 (), 0 }; + acceptor.open (endpoint.protocol ()); + + boost::asio::socket_base::reuse_address option{ true }; + acceptor.set_option (option); // set SO_REUSEADDR option + + acceptor.bind (endpoint); + + auto actual_endpoint = acceptor.local_endpoint (); + auto port = actual_endpoint.port (); + + acceptor.close (); + + return port; +} \ No newline at end of file diff --git a/nano/test_common/network.hpp b/nano/test_common/network.hpp index ddfb3619cd..c8835139fe 100644 --- a/nano/test_common/network.hpp +++ b/nano/test_common/network.hpp @@ -18,7 +18,11 @@ namespace test class system; /** Waits until a TCP connection is established and returns the TCP channel on success*/ std::shared_ptr establish_tcp (nano::test::system &, nano::node &, nano::endpoint const &); + /** Adds a node to the system without establishing connections */ std::shared_ptr add_outer_node (nano::test::system & system, nano::node_flags = nano::node_flags ()); + + /** speculatively (it is not guaranteed that the port will remain free) find a free tcp binding port and return it */ + uint16_t speculatively_choose_a_free_tcp_bind_port (); } } diff --git a/nano/test_common/system.cpp b/nano/test_common/system.cpp index b0f2ff1dfc..19a57c812c 100644 --- a/nano/test_common/system.cpp +++ b/nano/test_common/system.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include @@ -40,8 +42,8 @@ std::shared_ptr nano::test::system::add_node (nano::node_config cons auto node (std::make_shared (io_ctx, nano::unique_path (), node_config_a, work, node_flags_a, node_sequence++)); for (auto i : initialization_blocks) { - auto result = node->ledger.process (node->store.tx_begin_write (), *i); - debug_assert (result.code == nano::process_result::progress); + auto result = node->ledger.process (node->store.tx_begin_write (), i); + debug_assert (result == nano::block_status::progress); } debug_assert (!node->init_error ()); auto wallet = node->wallets.create (nano::random_wallet_id ()); @@ -122,6 +124,21 @@ std::shared_ptr nano::test::system::add_node (nano::node_config cons debug_assert (!ec); } + logger.debug (nano::log::type::system, "Node started: {}", node->get_node_id ().to_node_id ()); + + return node; +} + +std::shared_ptr nano::test::system::make_disconnected_node (std::optional opt_node_config, nano::node_flags flags) +{ + nano::node_config node_config = opt_node_config.has_value () ? *opt_node_config : default_config (); + auto node = std::make_shared (io_ctx, nano::unique_path (), node_config, work, flags); + if (node->init_error ()) + { + std::cerr << "node init error\n"; + return nullptr; + } + node->start (); return node; } @@ -132,7 +149,6 @@ nano::test::system::system () { deadline_scaling_factor = std::stod (scale_str); } - logging.init (nano::unique_path ()); } nano::test::system::system (uint16_t count_a, nano::transport::transport_type type_a, nano::node_flags flags_a) : @@ -180,7 +196,7 @@ void nano::test::system::ledger_initialization_set (std::vector c .balance (balance) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .work (*work.generate (previous)); - initialization_blocks.emplace_back (builder.build_shared ()); + initialization_blocks.emplace_back (builder.build ()); previous = initialization_blocks.back ()->hash (); builder.make_block (); builder.account (i.pub) @@ -190,7 +206,7 @@ void nano::test::system::ledger_initialization_set (std::vector c .balance (amount) .sign (i.prv, i.pub) .work (*work.generate (i.pub)); - initialization_blocks.emplace_back (builder.build_shared ()); + initialization_blocks.emplace_back (builder.build ()); } } @@ -227,7 +243,7 @@ uint64_t nano::test::system::work_generate_limited (nano::block_hash const & roo /** Initiate an epoch upgrade. Writes the epoch block into the ledger and leaves it to * node background processes (e.g. frontiers confirmation) to cement the block. */ -std::unique_ptr nano::test::upgrade_epoch (nano::work_pool & pool_a, nano::ledger & ledger_a, nano::epoch epoch_a) +std::shared_ptr nano::test::upgrade_epoch (nano::work_pool & pool_a, nano::ledger & ledger_a, nano::epoch epoch_a) { auto transaction (ledger_a.store.tx_begin_write ()); auto dev_genesis_key = nano::dev::genesis_key; @@ -250,13 +266,13 @@ std::unique_ptr nano::test::upgrade_epoch (nano::work_pool & bool error{ true }; if (!ec && epoch) { - error = ledger_a.process (transaction, *epoch).code != nano::process_result::progress; + error = ledger_a.process (transaction, epoch) != nano::block_status::progress; } return !error ? std::move (epoch) : nullptr; } -std::unique_ptr nano::test::system::upgrade_genesis_epoch (nano::node & node_a, nano::epoch const epoch_a) +std::shared_ptr nano::test::system::upgrade_genesis_epoch (nano::node & node_a, nano::epoch const epoch_a) { return upgrade_epoch (work, node_a.ledger, epoch_a); } @@ -404,12 +420,12 @@ void nano::test::system::generate_receive (nano::node & node_a) if (i != node_a.store.pending.end ()) { nano::pending_key const & send_hash (i->first); - send_block = node_a.store.block.get (transaction, send_hash.hash); + send_block = node_a.ledger.block (transaction, send_hash.hash); } } if (send_block != nullptr) { - auto receive_error (wallet (0)->receive_sync (send_block, nano::dev::genesis->account (), std::numeric_limits::max ())); + auto receive_error (wallet (0)->receive_sync (send_block, nano::dev::genesis_key.pub, std::numeric_limits::max ())); (void)receive_error; } } @@ -563,66 +579,36 @@ void nano::test::system::stop () nano::node_config nano::test::system::default_config () { - nano::node_config config{ get_available_port (), logging }; + nano::node_config config{ get_available_port () }; return config; } -uint16_t nano::test::system::get_available_port (bool can_be_zero) +uint16_t nano::test::system::get_available_port () { auto base_port_str = std::getenv ("NANO_TEST_BASE_PORT"); - if (base_port_str) - { - // Maximum possible sockets which may feasibly be used in 1 test - constexpr auto max = 200; - static uint16_t current = 0; - // Read the TEST_BASE_PORT environment and override the default base port if it exists - uint16_t base_port = boost::lexical_cast (base_port_str); - - uint16_t const available_port = base_port + current; - ++current; - // Reset port number once we have reached the maximum - if (current == max) - { - current = 0; - } + if (!base_port_str) + return 0; // let the O/S decide - return available_port; - } - else - { - if (!can_be_zero) - { - /* - * This works because the kernel doesn't seem to reuse port numbers until it absolutely has to. - * Subsequent binds to port 0 will allocate a different port number. - */ - boost::asio::ip::tcp::acceptor acceptor{ io_ctx }; - boost::asio::ip::tcp::tcp::endpoint endpoint{ boost::asio::ip::tcp::v4 (), 0 }; - acceptor.open (endpoint.protocol ()); - - boost::asio::socket_base::reuse_address option{ true }; - acceptor.set_option (option); // set SO_REUSEADDR option + // Maximum possible sockets which may feasibly be used in 1 test + constexpr auto max = 200; + static uint16_t current = 0; - acceptor.bind (endpoint); + // Read the TEST_BASE_PORT environment and override the default base port if it exists + uint16_t base_port = boost::lexical_cast (base_port_str); - auto actual_endpoint = acceptor.local_endpoint (); - auto port = actual_endpoint.port (); + uint16_t const available_port = base_port + current; + ++current; - acceptor.close (); + // Reset port number once we have reached the maximum + if (current >= max) + current = 0; - return port; - } - else - { - return 0; - } - } + return available_port; } +// Makes sure everything is cleaned up void nano::test::cleanup_dev_directories_on_exit () { - // Makes sure everything is cleaned up - nano::logging::release_file_sink (); // Clean up tmp directories created by the tests. Since it's sometimes useful to // see log files after test failures, an environment variable is supported to // retain the files. diff --git a/nano/test_common/system.hpp b/nano/test_common/system.hpp index e03532ccef..4230742e90 100644 --- a/nano/test_common/system.hpp +++ b/nano/test_common/system.hpp @@ -5,6 +5,7 @@ #include #include +#include namespace nano { @@ -37,7 +38,7 @@ namespace test void generate_receive (nano::node &); void generate_send_new (nano::node &, std::vector &); void generate_send_existing (nano::node &, std::vector &); - std::unique_ptr upgrade_genesis_epoch (nano::node &, nano::epoch const); + std::shared_ptr upgrade_genesis_epoch (nano::node &, nano::epoch const); std::shared_ptr wallet (size_t); nano::account account (store::transaction const &, size_t); /** Generate work with difficulty between \p min_difficulty_a (inclusive) and \p max_difficulty_a (exclusive) */ @@ -57,17 +58,26 @@ namespace test nano::node & node (std::size_t index) const; std::shared_ptr add_node (nano::node_flags = nano::node_flags (), nano::transport::transport_type = nano::transport::transport_type::tcp); std::shared_ptr add_node (nano::node_config const &, nano::node_flags = nano::node_flags (), nano::transport::transport_type = nano::transport::transport_type::tcp, std::optional const & rep = std::nullopt); + + // Make an independent node that uses system resources but is not part of the system node list and does not automatically connect to other nodes + std::shared_ptr make_disconnected_node (std::optional opt_node_config = std::nullopt, nano::node_flags = nano::node_flags ()); + /* * Returns default config for node running in test environment */ nano::node_config default_config (); - uint16_t get_available_port (bool can_be_zero = true); + + /* + * Returns port 0 by default, to let the O/S choose a port number. + * If NANO_TEST_BASE_PORT is set then it allocates numbers by itself from that range. + */ + uint16_t get_available_port (); public: boost::asio::io_context io_ctx; std::vector> nodes; - nano::logging logging; nano::stats stats; + nano::logger logger{ "tests" }; nano::work_pool work{ nano::dev::network_params.network, std::max (nano::hardware_concurrency (), 1u) }; std::chrono::time_point> deadline{ std::chrono::steady_clock::time_point::max () }; double deadline_scaling_factor{ 1.0 }; @@ -75,7 +85,7 @@ namespace test std::vector> initialization_blocks; }; - std::unique_ptr upgrade_epoch (nano::work_pool &, nano::ledger &, nano::epoch); + std::shared_ptr upgrade_epoch (nano::work_pool &, nano::ledger &, nano::epoch); void cleanup_dev_directories_on_exit (); } } diff --git a/nano/test_common/testutil.cpp b/nano/test_common/testutil.cpp index 56d89419f1..ce80cfeae0 100644 --- a/nano/test_common/testutil.cpp +++ b/nano/test_common/testutil.cpp @@ -1,8 +1,11 @@ #include +#include #include #include #include #include +#include +#include #include #include @@ -63,8 +66,8 @@ bool nano::test::process (nano::node & node, std::vector hashes) +{ + auto transaction = node.store.tx_begin_read (); + return std::all_of (hashes.begin (), hashes.end (), + [&] (const auto & hash) { + return node.ledger.block_or_pruned_exists (transaction, hash); + }); +} + +bool nano::test::block_or_pruned_all_exists (nano::node & node, std::vector> blocks) +{ + return block_or_pruned_all_exists (node, blocks_to_hashes (blocks)); +} + +bool nano::test::block_or_pruned_none_exists (nano::node & node, std::vector hashes) +{ + auto transaction = node.store.tx_begin_read (); + return std::none_of (hashes.begin (), hashes.end (), + [&] (const auto & hash) { + return node.ledger.block_or_pruned_exists (transaction, hash); + }); +} + +bool nano::test::block_or_pruned_none_exists (nano::node & node, std::vector> blocks) +{ + return block_or_pruned_none_exists (node, blocks_to_hashes (blocks)); +} + bool nano::test::activate (nano::node & node, std::vector hashes) { for (auto & hash : hashes) @@ -245,6 +276,28 @@ bool nano::test::start_elections (nano::test::system & system_a, nano::node & no return nano::test::start_elections (system_a, node_a, blocks_to_hashes (blocks_a), forced_a); } +nano::account_info nano::test::account_info (nano::node const & node, nano::account const & acc) +{ + auto const tx = node.ledger.store.tx_begin_read (); + auto opt = node.ledger.account_info (tx, acc); + if (opt.has_value ()) + { + return opt.value (); + } + return {}; +} + +uint64_t nano::test::account_height (nano::node const & node, nano::account const & acc) +{ + auto const tx = node.ledger.store.tx_begin_read (); + nano::confirmation_height_info height_info; + if (node.ledger.store.confirmation_height.get (tx, acc, height_info)) + { + return 0; + } + return height_info.height; +} + void nano::test::print_all_account_info (nano::node & node) { auto const tx = node.ledger.store.tx_begin_read (); @@ -264,4 +317,23 @@ void nano::test::print_all_account_info (nano::node & node) std::cout << " Conf. Frontier: " << height_info.frontier.to_string () << std::endl; } } -} \ No newline at end of file +} + +void nano::test::print_all_blocks (nano::node & node) +{ + auto tx = node.store.tx_begin_read (); + auto i = node.store.block.begin (tx); + auto end = node.store.block.end (); + std::cout << "Listing all blocks" << std::endl; + for (; i != end; ++i) + { + nano::block_hash hash = i->first; + nano::store::block_w_sideband sideband = i->second; + std::shared_ptr b = sideband.block; + std::cout << "Hash: " << hash.to_string () << std::endl; + const auto acc = sideband.sideband.account; + std::cout << "Acc: " << acc.to_string () << "(" << acc.to_account () << ")" << std::endl; + std::cout << "Height: " << sideband.sideband.height << std::endl; + std::cout << b->to_json (); + } +} diff --git a/nano/test_common/testutil.hpp b/nano/test_common/testutil.hpp index 3203fdfb3e..60821e7ddd 100644 --- a/nano/test_common/testutil.hpp +++ b/nano/test_common/testutil.hpp @@ -3,12 +3,11 @@ #include #include #include +#include #include #include -#include -#include #include #include @@ -136,54 +135,6 @@ namespace test { class system; - class stringstream_mt_sink : public boost::iostreams::sink - { - public: - stringstream_mt_sink () = default; - stringstream_mt_sink (stringstream_mt_sink const & sink) - { - nano::lock_guard guard{ mutex }; - ss << sink.ss.str (); - } - - std::streamsize write (char const * string_to_write, std::streamsize size) - { - nano::lock_guard guard{ mutex }; - ss << std::string (string_to_write, size); - return size; - } - - std::string str () - { - nano::lock_guard guard{ mutex }; - return ss.str (); - } - - private: - mutable nano::mutex mutex; - std::stringstream ss; - }; - - class boost_log_cerr_redirect - { - public: - boost_log_cerr_redirect (std::streambuf * new_buffer) : - old (std::cerr.rdbuf (new_buffer)) - { - console_sink = (boost::log::add_console_log (std::cerr, boost::log::keywords::format = "%Message%")); - } - - ~boost_log_cerr_redirect () - { - std::cerr.rdbuf (old); - boost::log::core::get ()->remove_sink (console_sink); - } - - private: - std::streambuf * old; - boost::shared_ptr> console_sink; - }; - class cout_redirect { public: @@ -350,6 +301,26 @@ namespace test * @return true if all blocks are fully processed and inserted in the ledger, false otherwise */ bool exists (nano::node & node, std::vector> blocks); + /* + * Convenience function to check whether *all* of the hashes exists in node ledger or in the pruned table. + * @return true if all blocks are fully processed and inserted in the ledger, false otherwise + */ + bool block_or_pruned_all_exists (nano::node & node, std::vector hashes); + /* + * Convenience function to check whether *all* of the blocks exists in node ledger or their hash exists in the pruned table. + * @return true if all blocks are fully processed and inserted in the ledger, false otherwise + */ + bool block_or_pruned_all_exists (nano::node & node, std::vector> blocks); + /* + * Convenience function to check whether *none* of the hashes exists in node ledger or in the pruned table. + * @return true if none of the blocks are processed and inserted in the ledger, false otherwise + */ + bool block_or_pruned_none_exists (nano::node & node, std::vector hashes); + /* + * Convenience function to check whether *none* of the blocks exists in node ledger or their hash exists in the pruned table. + * @return true if none of the blocks are processed and inserted in the ledger, false otherwise + */ + bool block_or_pruned_none_exists (nano::node & node, std::vector> blocks); /* * Convenience function to start elections for a list of hashes. Blocks are loaded from ledger. * @return true if all blocks exist and were queued to election scheduler @@ -417,11 +388,24 @@ namespace test */ [[nodiscard]] bool start_elections (nano::test::system &, nano::node &, std::vector> const &, bool const forced_a = false); + /** + * Return account_info for account "acc", if account is not found, a default initialised object is returned + */ + nano::account_info account_info (nano::node const & node, nano::account const & acc); + + /** + * Return the account height, returns 0 on error + */ + uint64_t account_height (nano::node const & node, nano::account const & acc); + /** * \brief Debugging function to print all accounts in a ledger. Intented to be used to debug unit tests. - * \param ledger */ void print_all_account_info (nano::node & node); + /** + * \brief Debugging function to print all blocks in a node. Intented to be used to debug unit tests. + */ + void print_all_blocks (nano::node & node); } } diff --git a/rep_weights_beta.bin b/rep_weights_beta.bin deleted file mode 100644 index 9657dd0752..0000000000 Binary files a/rep_weights_beta.bin and /dev/null differ diff --git a/submodules/fmt b/submodules/fmt new file mode 160000 index 0000000000..a0b8a92e3d --- /dev/null +++ b/submodules/fmt @@ -0,0 +1 @@ +Subproject commit a0b8a92e3d1532361c2f7feb63babc5c18d00ef2 diff --git a/submodules/magic_enum b/submodules/magic_enum index 533c9509ef..e55b9b54d5 160000 --- a/submodules/magic_enum +++ b/submodules/magic_enum @@ -1 +1 @@ -Subproject commit 533c9509ef77d0fedd8be47d16dc6310877e24cf +Subproject commit e55b9b54d5cf61f8e117cafb17846d7d742dd3b4 diff --git a/submodules/spdlog b/submodules/spdlog new file mode 160000 index 0000000000..7e635fca68 --- /dev/null +++ b/submodules/spdlog @@ -0,0 +1 @@ +Subproject commit 7e635fca68d014934b4af8a1cf874f63989352b7 diff --git a/systest/node_initialize.sh b/systest/node_initialize.sh index bf434f27c3..70e98f3598 100755 --- a/systest/node_initialize.sh +++ b/systest/node_initialize.sh @@ -41,7 +41,7 @@ mkdir -p "$DATADIR/log" #test_initialize_cmd "live" "" "" "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" test_initialize_cmd "live" "--network" "live" "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" -test_initialize_cmd "beta" "--network" "beta" "01A92459E69440D5C1088D3B31F4CA678BE944BAB3776C2E6B7665E9BD99BD5A" +test_initialize_cmd "beta" "--network" "beta" "E1227CF974C1455A8B630433D94F3DDBF495EEAC9ADD2481A4A1D90A0D00F488" test_initialize_cmd "test" "--network" "test" "B1D60C0B886B57401EF5A1DAA04340E53726AA6F4D706C085706F31BBD100CEE" # if it got this far then it is a pass