aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/actions/set-make-job-count/action.yml22
-rw-r--r--.github/workflows/build.yml339
-rw-r--r--.github/workflows/depends.yml51
-rw-r--r--.github/workflows/gitian.yml2
-rw-r--r--CMakeLists.txt55
-rw-r--r--README.md12
-rw-r--r--contrib/brew/Brewfile2
-rw-r--r--contrib/depends/packages/boost.mk10
-rw-r--r--contrib/epee/include/byte_stream.h2
-rw-r--r--contrib/epee/include/file_io_utils.h1
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h11
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl24
-rw-r--r--contrib/epee/include/net/http_server_handlers_map2.h7
-rw-r--r--contrib/epee/include/net/network_throttle-detail.hpp4
-rw-r--r--contrib/epee/include/serialization/keyvalue_serialization.h18
-rw-r--r--contrib/epee/include/span.h23
-rw-r--r--contrib/epee/include/storages/portable_storage_val_converters.h1
-rw-r--r--contrib/epee/include/string_tools.h5
-rw-r--r--contrib/epee/src/byte_slice.cpp8
-rw-r--r--contrib/epee/src/file_io_utils.cpp35
-rw-r--r--contrib/epee/src/mlog.cpp5
-rw-r--r--contrib/epee/src/network_throttle-detail.cpp28
-rw-r--r--contrib/epee/src/readline_buffer.cpp3
-rw-r--r--contrib/epee/src/string_tools.cpp22
-rw-r--r--contrib/gitian/DOCKRUN.md2
-rw-r--r--contrib/gitian/README.md2
-rw-r--r--external/CMakeLists.txt1
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp72
-rw-r--r--src/blocks/checkpoints.datbin387844 -> 399748 bytes
-rw-r--r--src/checkpoints/checkpoints.cpp1
-rw-r--r--src/common/download.cpp8
-rw-r--r--src/common/password.cpp2
-rw-r--r--src/crypto/crypto.h14
-rw-r--r--src/crypto/generic-ops.h9
-rw-r--r--src/cryptonote_basic/connection_context.cpp20
-rw-r--r--src/cryptonote_basic/connection_context.h10
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp4
-rw-r--r--src/cryptonote_config.h4
-rw-r--r--src/cryptonote_core/blockchain.cpp98
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp4
-rw-r--r--src/cryptonote_protocol/block_queue.cpp29
-rw-r--r--src/cryptonote_protocol/block_queue.h3
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h1
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl116
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp2
-rw-r--r--src/daemon/command_parser_executor.cpp10
-rw-r--r--src/device/device_default.cpp8
-rw-r--r--src/device/device_ledger.cpp1
-rw-r--r--src/lmdb/key_stream.h1
-rw-r--r--src/lmdb/table.h2
-rw-r--r--src/lmdb/util.h5
-rw-r--r--src/lmdb/value_stream.h4
-rw-r--r--src/p2p/net_node.h6
-rw-r--r--src/p2p/net_node.inl83
-rw-r--r--src/rpc/core_rpc_server.cpp6
-rw-r--r--src/rpc/daemon_handler.cpp2
-rw-r--r--src/rpc/message_data_structs.h1
-rw-r--r--src/serialization/json_object.cpp31
-rw-r--r--src/serialization/json_object.h2
-rw-r--r--src/simplewallet/simplewallet.cpp6
-rw-r--r--src/version.cpp.in2
-rw-r--r--src/wallet/api/wallet.cpp8
-rw-r--r--src/wallet/wallet2.cpp36
-rw-r--r--src/wallet/wallet2.h14
-rw-r--r--src/wallet/wallet_rpc_server.cpp15
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
-rw-r--r--tests/benchmark.cpp2
-rw-r--r--tests/core_tests/multisig.cpp10
-rwxr-xr-xtests/create_test_disks.sh98
-rw-r--r--tests/data/node/banlist_1.txt17
-rw-r--r--tests/functional_tests/make_test_signature.cc2
-rw-r--r--tests/unit_tests/crypto.cpp2
-rw-r--r--tests/unit_tests/dns_resolver.cpp12
-rw-r--r--tests/unit_tests/epee_serialization.cpp68
-rw-r--r--tests/unit_tests/epee_utils.cpp15
-rw-r--r--tests/unit_tests/is_hdd.cpp37
-rw-r--r--tests/unit_tests/json_serialization.cpp62
-rw-r--r--tests/unit_tests/levin.cpp57
-rw-r--r--tests/unit_tests/multisig.cpp2
-rw-r--r--tests/unit_tests/node_server.cpp97
-rw-r--r--tests/unit_tests/serialization.cpp2
-rw-r--r--utils/fish/monerod.fish4
-rw-r--r--utils/systemd/monerod.service2
83 files changed, 1284 insertions, 542 deletions
diff --git a/.github/actions/set-make-job-count/action.yml b/.github/actions/set-make-job-count/action.yml
new file mode 100644
index 000000000..68779ef3f
--- /dev/null
+++ b/.github/actions/set-make-job-count/action.yml
@@ -0,0 +1,22 @@
+name: 'set-make-job-count'
+description: 'Set the MAKE_JOB_COUNT environment variable to a value suitable for the host runner'
+runs:
+ using: "composite"
+ steps:
+ # Each job runner requires 2.25 GiB (i.e. 1024 * 9/4 MiB) memory and
+ # a dedicated logical CPU core
+ - name: set-jobs-macOS
+ if: runner.os == 'macOS'
+ run: |
+ echo MAKE_JOB_COUNT=$(expr $(printf '%s\n%s' $(( $(sysctl -n hw.memsize) * 4 / (1073741824 * 9) )) $(sysctl -n hw.logicalcpu) | sort -n | head -n1) '|' 1) >> $GITHUB_ENV
+ shell: bash
+ - name: set-jobs-windows
+ if: runner.os == 'Windows'
+ run: |
+ echo MAKE_JOB_COUNT=$(expr $(printf '%s\n%s' $(( $(grep MemTotal: /proc/meminfo | cut -d: -f2 | cut -dk -f1) * 4 / (1048576 * 9) )) $(nproc) | sort -n | head -n1) '|' 1) >> $GITHUB_ENV
+ shell: msys2 {0}
+ - name: set-jobs-linux
+ if: runner.os == 'Linux'
+ run: |
+ echo MAKE_JOB_COUNT=$(expr $(printf '%s\n%s' $(( $(grep MemTotal: /proc/meminfo | cut -d: -f2 | cut -dk -f1) * 4 / (1048576 * 9) )) $(nproc) | sort -n | head -n1) '|' 1) >> $GITHUB_ENV
+ shell: bash
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4c1e381c0..29926e23d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,6 +2,9 @@ name: ci/gh-actions/cli
on:
push:
+ paths-ignore:
+ - 'docs/**'
+ - '**/README.md'
pull_request:
paths-ignore:
- 'docs/**'
@@ -9,40 +12,46 @@ on:
# The below variables reduce repetitions across similar targets
env:
- REMOVE_BUNDLED_BOOST : rm -rf /usr/local/share/boost
- BUILD_DEFAULT_LINUX: |
- cmake -S . -B build -D ARCH="default" -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release && cmake --build build -j3
- APT_INSTALL_LINUX: 'sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler ccache'
+ # ARCH="default" (not "native") ensures, that a different execution host can execute binaries compiled elsewhere.
+ BUILD_DEFAULT_LINUX: 'cmake -S . -B build -D ARCH="default" -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release && cmake --build build --target all && cmake --build build --target wallet_api'
+ APT_INSTALL_LINUX: 'apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler ccache git'
APT_SET_CONF: |
- echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
- echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
- echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
+ tee -a /etc/apt/apt.conf.d/80-custom << EOF
+ Acquire::Retries "3";
+ Acquire::http::Timeout "120";
+ Acquire::ftp::Timeout "120";
+ EOF
CCACHE_SETTINGS: |
- ccache --max-size=150M
- ccache --set-config=compression=true
+ ccache --max-size=150M
+ ccache --set-config=compression=true
jobs:
build-macos:
+ name: 'macOS (brew)'
runs-on: macOS-latest
env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - uses: actions/cache@v3
- with:
- path: /Users/runner/Library/Caches/ccache
- key: ccache-${{ runner.os }}-build-${{ github.sha }}
- restore-keys: ccache-${{ runner.os }}-build-
- - name: install dependencies
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi openssl zmq libpgm miniupnpc expat libunwind-headers protobuf ccache
- - name: build
- run: |
- ${{env.CCACHE_SETTINGS}}
- make -j3
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: actions/cache@v4
+ with:
+ path: /Users/runner/Library/Caches/ccache
+ key: ccache-${{ runner.os }}-build-${{ github.sha }}
+ restore-keys: ccache-${{ runner.os }}-build-
+ - uses: ./.github/actions/set-make-job-count
+ - name: install dependencies
+ run: |
+ HOMEBREW_NO_AUTO_UPDATE=1 brew install boost@1.85 hidapi openssl zmq libpgm miniupnpc expat libunwind-headers protobuf ccache
+ brew link boost@1.85
+ - name: build
+ run: |
+ ${{env.CCACHE_SETTINGS}}
+ make -j${{env.MAKE_JOB_COUNT}}
build-windows:
+ name: 'Windows (MSYS2)'
runs-on: windows-latest
env:
CCACHE_TEMPDIR: C:\Users\runneradmin\.ccache-temp
@@ -51,134 +60,184 @@ jobs:
run:
shell: msys2 {0}
steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - uses: actions/cache@v3
- with:
- path: C:\Users\runneradmin\.ccache
- key: ccache-${{ runner.os }}-build-${{ github.sha }}
- restore-keys: ccache-${{ runner.os }}-build-
- - uses: msys2/setup-msys2@v2
- with:
- update: true
- install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-ccache mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git
- - name: build
- run: |
- ${{env.CCACHE_SETTINGS}}
- make release-static-win64 -j2
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: actions/cache@v4
+ with:
+ path: C:\Users\runneradmin\.ccache
+ key: ccache-${{ runner.os }}-build-${{ github.sha }}
+ restore-keys: ccache-${{ runner.os }}-build-
+ - uses: msys2/setup-msys2@v2
+ with:
+ update: true
+ install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-ccache mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git
+ - shell: msys2 {0}
+ run: |
+ curl -O https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-boost-1.86.0-7-any.pkg.tar.zst
+ echo "3e84674b4d2b3ab82f4d5e22bcc2015fa139b6fd936c55d6b71f89a72a1ee0a2 mingw-w64-x86_64-boost-1.86.0-7-any.pkg.tar.zst" | sha256sum -c
+ curl -O https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-boost-libs-1.86.0-7-any.pkg.tar.zst
+ echo "4cb1d1066fffa6a5788b212ccb920c6d8cc93a8ecbbc633565bfc9b2ebc6feb5 mingw-w64-x86_64-boost-libs-1.86.0-7-any.pkg.tar.zst" | sha256sum -c
+ curl -O https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-icu-75.1-2-any.pkg.tar.zst
+ echo "bf57882d43efcdfd746463613ea982c69b64aa4ba9bed4cb24c02a81ad06c3a9 mingw-w64-x86_64-icu-75.1-2-any.pkg.tar.zst" | sha256sum -c
+ pacman --noconfirm -U mingw-w64-x86_64-boost-1.86.0-7-any.pkg.tar.zst mingw-w64-x86_64-boost-libs-1.86.0-7-any.pkg.tar.zst mingw-w64-x86_64-icu-75.1-2-any.pkg.tar.zst
+ - uses: ./.github/actions/set-make-job-count
+ - name: build
+ run: |
+ ${{env.CCACHE_SETTINGS}}
+ make release-static-win64 -j${{env.MAKE_JOB_COUNT}}
-# See the OS labels and monitor deprecations here:
-# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
+ build-debian:
+ # Oldest supported Debian version
+ name: 'Debian 10'
+ runs-on: ubuntu-latest
+ container:
+ image: debian:10
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ steps:
+ - name: set apt conf
+ run: ${{env.APT_SET_CONF}}
+ - name: update apt
+ run: apt update
+ - name: install monero dependencies
+ run: ${{env.APT_INSTALL_LINUX}}
+ - name: configure git
+ run: git config --global --add safe.directory '*'
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: ./.github/actions/set-make-job-count
+ - name: build
+ env:
+ CMAKE_BUILD_PARALLEL_LEVEL: ${{env.MAKE_JOB_COUNT}}
+ run: ${{env.BUILD_DEFAULT_LINUX}}
build-ubuntu:
- runs-on: ${{ matrix.os }}
- env:
- CCACHE_TEMPDIR: /tmp/.ccache-temp
+ name: ${{ matrix.name }}
+ runs-on: ubuntu-latest
strategy:
+ fail-fast: false
matrix:
- os: [ubuntu-22.04, ubuntu-20.04]
- steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - uses: actions/cache@v3
- with:
- path: ~/.ccache
- key: ccache-${{ runner.os }}-build-${{ matrix.os }}-${{ github.sha }}
- restore-keys: ccache-${{ runner.os }}-build-${{ matrix.os }}
- - name: remove bundled boost
- run: ${{env.REMOVE_BUNDLED_BOOST}}
- - name: set apt conf
- run: ${{env.APT_SET_CONF}}
- - name: update apt
- run: sudo apt update
- - name: install monero dependencies
- run: ${{env.APT_INSTALL_LINUX}}
- - name: build
- run: |
- ${{env.CCACHE_SETTINGS}}
- ${{env.BUILD_DEFAULT_LINUX}}
+ include:
+ # Oldest supported Ubuntu LTS version
+ - name: Ubuntu 20.04
+ container: ubuntu:20.04
- libwallet-ubuntu:
- runs-on: ubuntu-20.04
- env:
- CCACHE_TEMPDIR: /tmp/.ccache-temp
+ # Most popular Ubuntu LTS version
+ - name: Ubuntu 22.04
+ container: ubuntu:22.04
+ container:
+ image: ${{ matrix.container }}
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ CCACHE_TEMPDIR: /tmp/.ccache-temp
+ CCACHE_DIR: ~/.ccache
steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - uses: actions/cache@v3
- with:
- path: ~/.ccache
- key: ccache-${{ runner.os }}-libwallet-${{ github.sha }}
- restore-keys: ccache-${{ runner.os }}-libwallet-
- - name: remove bundled boost
- run: ${{env.REMOVE_BUNDLED_BOOST}}
- - name: set apt conf
- run: ${{env.APT_SET_CONF}}
- - name: update apt
- run: sudo apt update
- - name: install monero dependencies
- run: ${{env.APT_INSTALL_LINUX}}
- - name: build
- run: |
- ${{env.CCACHE_SETTINGS}}
- cmake .
- make wallet_api -j3
+ - name: set apt conf
+ run: ${{env.APT_SET_CONF}}
+ - name: update apt
+ run: apt update
+ - name: install monero dependencies
+ run: ${{env.APT_INSTALL_LINUX}}
+ - name: configure git
+ run: git config --global --add safe.directory '*'
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: actions/cache@v4
+ with:
+ path: ~/.ccache
+ key: ccache-${{ matrix.container }}-build-${{ github.sha }}
+ restore-keys: ccache-${{ matrix.container }}-build-
+ - uses: ./.github/actions/set-make-job-count
+ - name: build
+ env:
+ CMAKE_BUILD_PARALLEL_LEVEL: ${{env.MAKE_JOB_COUNT}}
+ run: |
+ ${{env.CCACHE_SETTINGS}}
+ ${{env.BUILD_DEFAULT_LINUX}}
test-ubuntu:
+ name: "${{ matrix.name }} (tests)"
needs: build-ubuntu
- runs-on: ubuntu-20.04
- env:
- CCACHE_TEMPDIR: /tmp/.ccache-temp
- steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - name: ccache
- uses: actions/cache@v3
- with:
- path: ~/.ccache
- key: ccache-${{ runner.os }}-build-ubuntu-latest-${{ github.sha }}
- restore-keys: ccache-${{ runner.os }}-build-ubuntu-latest
- - name: remove bundled boost
- run: ${{env.REMOVE_BUNDLED_BOOST}}
- - name: set apt conf
- run: ${{env.APT_SET_CONF}}
- - name: update apt
- run: sudo apt update
- - name: install monero dependencies
- run: ${{env.APT_INSTALL_LINUX}}
- - name: install Python dependencies
- run: pip install requests psutil monotonic zmq deepdiff
- - name: tests
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ include:
+ - name: Ubuntu 20.04
+ container: ubuntu:20.04
+ container:
+ image: ${{ matrix.container }}
env:
- CTEST_OUTPUT_ON_FAILURE: ON
- DNS_PUBLIC: tcp://9.9.9.9
- run: |
- ${{env.CCACHE_SETTINGS}}
- ${{env.BUILD_DEFAULT_LINUX}}
- cmake --build build --target test
-
-# ARCH="default" (not "native") ensures, that a different execution host can execute binaries compiled elsewhere.
-# BUILD_SHARED_LIBS=ON speeds up the linkage part a bit, reduces size, and is the only place where the dynamic linkage is tested.
+ DEBIAN_FRONTEND: noninteractive
+ CCACHE_TEMPDIR: /tmp/.ccache-temp
+ CCACHE_DIR: ~/.ccache
+ # Setting up a loop device (losetup) requires additional capabilities.
+ # tests/create_test_disks.sh
+ options: --privileged
+ steps:
+ - name: set apt conf
+ run: ${{env.APT_SET_CONF}}
+ - name: update apt
+ run: apt update
+ - name: install monero dependencies
+ run: ${{env.APT_INSTALL_LINUX}}
+ - name: install pip
+ run: apt install -y python3-pip
+ - name: install Python dependencies
+ run: pip install requests psutil monotonic zmq deepdiff
+ - name: configure git
+ run: git config --global --add safe.directory '*'
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: actions/cache@v4
+ with:
+ path: ~/.ccache
+ key: ccache-${{ matrix.container }}-build-${{ github.sha }}
+ restore-keys: ccache-${{ matrix.container }}-build-
+ - name: create dummy disk drives for testing
+ run: tests/create_test_disks.sh >> $GITHUB_ENV
+ - uses: ./.github/actions/set-make-job-count
+ - name: tests
+ env:
+ CTEST_OUTPUT_ON_FAILURE: ON
+ DNS_PUBLIC: tcp://9.9.9.9
+ CMAKE_BUILD_PARALLEL_LEVEL: ${{env.MAKE_JOB_COUNT}}
+ run: |
+ ${{env.CCACHE_SETTINGS}}
+ ${{env.BUILD_DEFAULT_LINUX}}
+ cmake --build build --target test
source-archive:
- runs-on: ubuntu-20.04
+ name: "source archive"
+ runs-on: ubuntu-latest
+ container:
+ image: ubuntu:20.04
+ env:
+ DEBIAN_FRONTEND: noninteractive
steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
- submodules: recursive
- - name: archive
- run: |
- pip install git-archive-all
- export VERSION="monero-$(git describe)"
- export OUTPUT="$VERSION.tar"
- echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
- /home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
- - uses: actions/upload-artifact@v3
- with:
- name: ${{ env.OUTPUT }}
- path: /home/runner/work/monero/monero/${{ env.OUTPUT }}
+ - name: set apt conf
+ run: ${{env.APT_SET_CONF}}
+ - name: update apt
+ run: apt update
+ - name: install dependencies
+ run: apt install -y git python3-pip
+ - name: configure git
+ run: git config --global --add safe.directory '*'
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: recursive
+ - name: archive
+ run: |
+ pip install git-archive-all
+ export VERSION="monero-$(git describe)"
+ export OUTPUT="$VERSION.tar"
+ echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
+ git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.OUTPUT }}
+ path: ${{ env.OUTPUT }}
diff --git a/.github/workflows/depends.yml b/.github/workflows/depends.yml
index 710a548a5..c754260b2 100644
--- a/.github/workflows/depends.yml
+++ b/.github/workflows/depends.yml
@@ -9,18 +9,23 @@ on:
env:
APT_SET_CONF: |
- echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
- echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
- echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
+ tee -a /etc/apt/apt.conf.d/80-custom << EOF
+ Acquire::Retries "3";
+ Acquire::http::Timeout "120";
+ Acquire::ftp::Timeout "120";
+ EOF
CCACHE_SETTINGS: |
ccache --max-size=150M
ccache --set-config=compression=true
jobs:
build-cross:
- runs-on: ubuntu-20.04
- env:
- CCACHE_TEMPDIR: /tmp/.ccache-temp
+ runs-on: ubuntu-latest
+ container:
+ image: ubuntu:20.04
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ CCACHE_TEMPDIR: /tmp/.ccache-temp
strategy:
fail-fast: false
matrix:
@@ -48,29 +53,35 @@ jobs:
packages: "gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
- name: "Cross-Mac x86_64"
host: "x86_64-apple-darwin11"
- packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
+ packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git libtinfo5"
- name: "Cross-Mac aarch64"
host: "aarch64-apple-darwin11"
- packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
+ packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git libtinfo5"
- name: "x86_64 Freebsd"
host: "x86_64-unknown-freebsd"
packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
name: ${{ matrix.toolchain.name }}
steps:
- - uses: actions/checkout@v3
+ - name: set apt conf
+ run: ${{env.APT_SET_CONF}}
+ - name: install dependencies
+ run: apt update; apt -y install build-essential libtool cmake autotools-dev automake pkg-config python3 gperf bsdmainutils curl git ca-certificates unzip ccache ${{ matrix.toolchain.packages }}
+ - name: configure git
+ run: git config --global --add safe.directory '*'
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
# Most volatile cache
- name: ccache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }}
restore-keys: ccache-${{ matrix.toolchain.host }}-
# Less volatile cache
- name: depends cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: contrib/depends/built
key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
@@ -79,28 +90,24 @@ jobs:
depends-${{ matrix.toolchain.host }}-
# Static cache
- name: OSX SDK cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: contrib/depends/sdk-sources
key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }}
restore-keys: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }}
- - name: set apt conf
- run: ${{env.APT_SET_CONF}}
- - name: install dependencies
- run: sudo apt update; sudo apt -y install build-essential libtool cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache ${{ matrix.toolchain.packages }}
- name: prepare w64-mingw32
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'i686-w64-mingw32' }}
run: |
- sudo update-alternatives --set ${{ matrix.toolchain.host }}-g++ $(which ${{ matrix.toolchain.host }}-g++-posix)
- sudo update-alternatives --set ${{ matrix.toolchain.host }}-gcc $(which ${{ matrix.toolchain.host }}-gcc-posix)
+ update-alternatives --set ${{ matrix.toolchain.host }}-g++ $(which ${{ matrix.toolchain.host }}-g++-posix)
+ update-alternatives --set ${{ matrix.toolchain.host }}-gcc $(which ${{ matrix.toolchain.host }}-gcc-posix)
- name: build
run: |
${{env.CCACHE_SETTINGS}}
- make depends target=${{ matrix.toolchain.host }} -j2
- - uses: actions/upload-artifact@v3
+ make depends target=${{ matrix.toolchain.host }} -j4
+ - uses: actions/upload-artifact@v4
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin11' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' }}
with:
name: ${{ matrix.toolchain.name }}
path: |
- /home/runner/work/monero/monero/build/${{ matrix.toolchain.host }}/release/bin/monero-wallet-cli*
- /home/runner/work/monero/monero/build/${{ matrix.toolchain.host }}/release/bin/monerod*
+ build/${{ matrix.toolchain.host }}/release/bin/monero-wallet-cli*
+ build/${{ matrix.toolchain.host }}/release/bin/monerod*
diff --git a/.github/workflows/gitian.yml b/.github/workflows/gitian.yml
index 91e60a88f..db9735ac3 100644
--- a/.github/workflows/gitian.yml
+++ b/.github/workflows/gitian.yml
@@ -42,7 +42,7 @@ jobs:
echo \`\`\` >> $GITHUB_STEP_SUMMARY
shasum -a256 * >> $GITHUB_STEP_SUMMARY
echo \`\`\` >> $GITHUB_STEP_SUMMARY
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: ${{ matrix.operating-system.name }}
path: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8fb03ba1f..db69b1b04 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1075,25 +1075,43 @@ if(STATIC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
-find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
-add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
-set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
+# Find Boost headers
+set(BOOST_MIN_VER 1.62)
+find_package(Boost ${BOOST_MIN_VER} QUIET REQUIRED)
+
if(NOT Boost_FOUND)
- die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=1.58) or the equivalent")
+ die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=${BOOST_MIN_VER}) or the equivalent")
elseif(Boost_FOUND)
- message(STATUS "Found Boost Version: ${Boost_VERSION}")
- if (Boost_VERSION VERSION_LESS 10 AND Boost_VERSION VERSION_LESS 1.62.0 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
- set(BOOST_BEFORE_1_62 true)
- endif()
- if (NOT Boost_VERSION VERSION_LESS 10 AND Boost_VERSION VERSION_LESS 106200 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
- set(BOOST_BEFORE_1_62 true)
+ message(STATUS "Found Boost Version: ${Boost_VERSION_STRING}")
+
+ set(BOOST_COMPONENTS filesystem thread date_time chrono serialization program_options locale)
+
+ # Boost System is header-only since 1.69
+ if (Boost_VERSION_STRING VERSION_LESS 1.69.0)
+ list(APPEND BOOST_COMPONENTS system)
endif()
- if (BOOST_BEFORE_1_62)
- message(FATAL_ERROR "Boost ${Boost_VERSION} (older than 1.62) is too old to link with OpenSSL ${OPENSSL_VERSION} (1.1 or newer) found at ${OPENSSL_INCLUDE_DIR} and ${OPENSSL_LIBRARIES}. "
- "Update Boost or install OpenSSL 1.0 and set path to it when running cmake: "
- "cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0'")
+
+ # Boost Regex is header-only since 1.77
+ if (Boost_VERSION_STRING VERSION_LESS 1.77.0)
+ list(APPEND BOOST_COMPONENTS regex)
endif()
+
+ message(STATUS "Boost components: ${BOOST_COMPONENTS}")
+
+ # Find required Boost libraries
+ find_package(Boost ${BOOST_MIN_VER} QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
+endif()
+
+add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
+add_definitions(-DBOOST_NO_AUTO_PTR)
+add_definitions(-DBOOST_UUID_DISABLE_ALIGNMENT) # This restores UUID's std::has_unique_object_representations property
+
+if(FREEBSD AND DEPENDS)
+ # Boost 1.66.0 fails to detect that we have <string_view>, resulting in an incorrect include.
+ # This line can be removed if Boost is upgraded to > 1.66.0.
+ add_definitions(-DBOOST_ASIO_HAS_STD_STRING_VIEW)
endif()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
@@ -1188,6 +1206,7 @@ endif()
if(NOT ZMQ_LIB)
message(FATAL_ERROR "Could not find required libzmq")
endif()
+include_directories(${ZMQ_INCLUDE_PATH})
if(PGM_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PGM_LIBRARY}")
endif()
@@ -1201,7 +1220,15 @@ if(PROTOLIB_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PROTOLIB_LIBRARY}")
endif()
if(SODIUM_LIBRARY)
+ message(STATUS "ZMQ_LIB: ${ZMQ_LIB};${SODIUM_LIBRARY}")
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
+ find_path(SODIUM_INCLUDE_PATH sodium/crypto_verify_32.h)
+ if (SODIUM_INCLUDE_PATH)
+ message(STATUS "SODIUM_INCLUDE_PATH: ${SODIUM_INCLUDE_PATH}")
+ include_directories(${SODIUM_INCLUDE_PATH})
+ else()
+ message(FATAL_ERROR "Could not find required sodium/crypto_verify_32.h")
+ endif()
endif()
if(BSD_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${BSD_LIBRARY}")
diff --git a/README.md b/README.md
index 8d84c8149..d47123296 100644
--- a/README.md
+++ b/README.md
@@ -138,8 +138,8 @@ Dates are provided in the format YYYY-MM-DD.
| 1978433 | 2019-11-30 | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.3.2 | New CLSAG transaction format
| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.3.2 | forbid old MLSAG transaction format
-| 2688888 | 2022-08-13 | v15 | v0.18.0.0 | v0.18.3.3 | ringsize = 16, bulletproofs+, view tags, adjusted dynamic block weight algorithm
-| 2689608 | 2022-08-14 | v16 | v0.18.0.0 | v0.18.3.3 | forbid old v14 transaction format
+| 2688888 | 2022-08-13 | v15 | v0.18.0.0 | v0.18.3.4 | ringsize = 16, bulletproofs+, view tags, adjusted dynamic block weight algorithm
+| 2689608 | 2022-08-14 | v16 | v0.18.0.0 | v0.18.3.4 | forbid old v14 transaction format
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
X's indicate that these details have not been determined as of commit date.
@@ -168,7 +168,7 @@ library archives (`.a`).
| GCC | 5 | NO | `build-essential` | `base-devel` | `base-devel` | `gcc` | NO | |
| CMake | 3.5 | NO | `cmake` | `cmake` | `cmake` | `cmake` | NO | |
| pkg-config | any | NO | `pkg-config` | `base-devel` | `base-devel` | `pkgconf` | NO | |
-| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | `boost-devel` | NO | C++ libraries |
+| Boost | 1.62 | NO | `libboost-all-dev` | `boost` | `boost-devel` | `boost-devel` | NO | C++ libraries |
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `libressl-devel` | `openssl-devel` | NO | sha256 sum |
| libzmq | 4.2.0 | NO | `libzmq3-dev` | `zeromq` | `zeromq-devel` | `zeromq-devel` | NO | ZeroMQ library |
| OpenPGM | ? | NO | `libpgm-dev` | `libpgm` | | `openpgm-devel` | NO | For ZeroMQ |
@@ -344,7 +344,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/monero-project/monero.git
cd monero
- git checkout v0.18.3.3
+ git checkout v0.18.3.4
```
* Build:
@@ -463,10 +463,10 @@ application.
cd monero
```
-* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.18.3.3'. If you don't care about the version and just want binaries from master, skip this step:
+* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.18.3.4'. If you don't care about the version and just want binaries from master, skip this step:
```bash
- git checkout v0.18.3.3
+ git checkout v0.18.3.4
```
* If you are on a 64-bit system, run:
diff --git a/contrib/brew/Brewfile b/contrib/brew/Brewfile
index c74e7b2a2..a159345cf 100644
--- a/contrib/brew/Brewfile
+++ b/contrib/brew/Brewfile
@@ -16,7 +16,7 @@ brew "binutils"
brew "coreutils"
brew "cmake"
brew "pkg-config"
-brew "boost"
+brew "boost@1.85", link: true
brew "openssl"
brew "hidapi"
brew "zmq"
diff --git a/contrib/depends/packages/boost.mk b/contrib/depends/packages/boost.mk
index fd06c5393..402fc84a5 100644
--- a/contrib/depends/packages/boost.mk
+++ b/contrib/depends/packages/boost.mk
@@ -1,8 +1,8 @@
package=boost
-$(package)_version=1_64_0
-$(package)_download_path=https://downloads.sourceforge.net/project/boost/boost/1.64.0/
-$(package)_file_name=$(package)_$($(package)_version).tar.bz2
-$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
+$(package)_version=1.66.0
+$(package)_download_path=https://archives.boost.io/release/$($(package)_version)/source/
+$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.gz
+$(package)_sha256_hash=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60
$(package)_dependencies=libiconv
$(package)_patches=fix_aroptions.patch fix_arm_arch.patch
@@ -25,7 +25,7 @@ $(package)_archiver_darwin=$($(package)_libtool)
$(package)_config_libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale
$(package)_cxxflags=-std=c++11
$(package)_cxxflags_linux=-fPIC
-$(package)_cxxflags_freebsd=-fPIC
+$(package)_cxxflags_freebsd=-fPIC -DBOOST_ASIO_HAS_STD_STRING_VIEW=1
endef
define $(package)_preprocess_cmds
diff --git a/contrib/epee/include/byte_stream.h b/contrib/epee/include/byte_stream.h
index e7993133a..ec9e5cbca 100644
--- a/contrib/epee/include/byte_stream.h
+++ b/contrib/epee/include/byte_stream.h
@@ -74,6 +74,7 @@ namespace epee
public:
using char_type = std::uint8_t;
using Ch = char_type;
+ using value_type = char_type;
//! Increase internal buffer by at least `byte_stream_increase` bytes.
byte_stream() noexcept
@@ -86,6 +87,7 @@ namespace epee
~byte_stream() noexcept = default;
byte_stream& operator=(byte_stream&& rhs) noexcept;
+ std::uint8_t* data() noexcept { return buffer_.get(); }
const std::uint8_t* data() const noexcept { return buffer_.get(); }
std::uint8_t* tellp() const noexcept { return next_write_; }
std::size_t available() const noexcept { return end_ - next_write_; }
diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h
index de95e58c3..107bf535a 100644
--- a/contrib/epee/include/file_io_utils.h
+++ b/contrib/epee/include/file_io_utils.h
@@ -38,7 +38,6 @@ namespace file_io_utils
bool is_file_exist(const std::string& path);
bool save_string_to_file(const std::string& path_to_file, const std::string& str);
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);
- bool get_file_size(const std::string& path_to_file, uint64_t &size);
}
}
diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
index bc0da66e2..be9999203 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.h
+++ b/contrib/epee/include/net/abstract_tcp_server2.h
@@ -76,6 +76,13 @@ namespace net_utils
protected:
virtual ~i_connection_filter(){}
};
+
+ struct i_connection_limit
+ {
+ virtual bool is_host_limit(const epee::net_utils::network_address &address)=0;
+ protected:
+ virtual ~i_connection_limit(){}
+ };
/************************************************************************/
@@ -260,10 +267,11 @@ namespace net_utils
struct shared_state : connection_basic_shared_state, t_protocol_handler::config_type
{
shared_state()
- : connection_basic_shared_state(), t_protocol_handler::config_type(), pfilter(nullptr), stop_signal_sent(false)
+ : connection_basic_shared_state(), t_protocol_handler::config_type(), pfilter(nullptr), plimit(nullptr), stop_signal_sent(false)
{}
i_connection_filter* pfilter;
+ i_connection_limit* plimit;
bool stop_signal_sent;
};
@@ -369,6 +377,7 @@ namespace net_utils
size_t get_threads_count(){return m_threads_count;}
void set_connection_filter(i_connection_filter* pfilter);
+ void set_connection_limit(i_connection_limit* plimit);
void set_default_remote(epee::net_utils::network_address remote)
{
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index d88f18194..8a3a8299c 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -328,7 +328,7 @@ namespace net_utils
return;
}
auto self = connection<T>::shared_from_this();
- if (m_connection_type != e_connection_type_RPC) {
+ if (speed_limit_is_enabled()) {
auto calc_duration = []{
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_in
@@ -382,7 +382,7 @@ namespace net_utils
m_conn_context.m_max_speed_down,
speed
);
- {
+ if (speed_limit_is_enabled()) {
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_in
);
@@ -454,7 +454,7 @@ namespace net_utils
return;
}
auto self = connection<T>::shared_from_this();
- if (m_connection_type != e_connection_type_RPC) {
+ if (speed_limit_is_enabled()) {
auto calc_duration = [this]{
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_out
@@ -513,7 +513,7 @@ namespace net_utils
m_conn_context.m_max_speed_down,
speed
);
- {
+ if (speed_limit_is_enabled()) {
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_out
);
@@ -873,6 +873,13 @@ namespace net_utils
).pfilter;
if (filter && !filter->is_remote_host_allowed(*real_remote))
return false;
+
+ auto *limit = static_cast<shared_state&>(
+ connection_basic::get_state()
+ ).plimit;
+ if (limit && limit->is_host_limit(*real_remote))
+ return false;
+
ec_t ec;
#if !defined(_WIN32) || !defined(__i686)
connection_basic::socket_.next_layer().set_option(
@@ -1022,7 +1029,7 @@ namespace net_utils
template<typename T>
bool connection<T>::speed_limit_is_enabled() const
{
- return m_connection_type != e_connection_type_RPC;
+ return m_connection_type == e_connection_type_P2P;
}
template<typename T>
@@ -1349,6 +1356,13 @@ namespace net_utils
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
+ void boosted_tcp_server<t_protocol_handler>::set_connection_limit(i_connection_limit* plimit)
+ {
+ assert(m_state != nullptr); // always set in constructor
+ m_state->plimit = plimit;
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
bool boosted_tcp_server<t_protocol_handler>::run_server(size_t threads_count, bool wait, const boost::thread::attributes& attrs)
{
TRY_ENTRY();
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h
index ffb3f3b7e..8d68f041b 100644
--- a/contrib/epee/include/net/http_server_handlers_map2.h
+++ b/contrib/epee/include/net/http_server_handlers_map2.h
@@ -171,6 +171,13 @@
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
return true; \
} \
+ epee::serialization::storage_entry params_; \
+ params_ = epee::serialization::storage_entry(epee::serialization::section()); \
+ if(!ps.get_value("params", params_, nullptr)) \
+ { \
+ epee::serialization::section params_section; \
+ ps.set_value("params", std::move(params_section), nullptr); \
+ } \
if(false) return true; //just a stub to have "else if"
diff --git a/contrib/epee/include/net/network_throttle-detail.hpp b/contrib/epee/include/net/network_throttle-detail.hpp
index 0a6dc4a20..3a88105c7 100644
--- a/contrib/epee/include/net/network_throttle-detail.hpp
+++ b/contrib/epee/include/net/network_throttle-detail.hpp
@@ -46,13 +46,13 @@ namespace net_utils
class network_throttle : public i_network_throttle {
- private:
+ public:
struct packet_info {
size_t m_size; // octets sent. Summary for given small-window (e.g. for all packaged in 1 second)
packet_info();
};
-
+ private:
network_speed_bps m_target_speed;
size_t m_network_add_cost; // estimated add cost of headers
size_t m_network_minimal_segment; // estimated minimal cost of sending 1 byte to round up to
diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h
index 06d74329f..fbbddc7d2 100644
--- a/contrib/epee/include/serialization/keyvalue_serialization.h
+++ b/contrib/epee/include/serialization/keyvalue_serialization.h
@@ -98,16 +98,18 @@ public: \
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
epee::serialization::selector<is_store>::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
-#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, val_name) \
- static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
- KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name)
+#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(variable, val_name) \
+ static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
+ static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
+ KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name)
-#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, val_name, default_value) \
+#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(variable, val_name, default_value) \
do { \
- static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
- bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name); \
+ static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
+ static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
+ bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name) \
if (!ret) \
- epee::serialize_default(this_ref.varialble, default_value); \
+ epee::serialize_default(this_ref.variable, default_value); \
} while(0);
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \
@@ -118,7 +120,7 @@ public: \
#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble)
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(varialble, def) KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, #varialble, def)
-#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check
+#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_trivially_copyable and is_standard_layout compile time check
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_OPT(variable,default_value) KV_SERIALIZE_OPT_N(variable, #variable, default_value)
diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h
index 23bd51f8c..01dc387d6 100644
--- a/contrib/epee/include/span.h
+++ b/contrib/epee/include/span.h
@@ -133,17 +133,14 @@ namespace epee
return {src.data(), src.size()};
}
- template<typename T>
- constexpr bool has_padding() noexcept
- {
- return !std::is_standard_layout<T>() || alignof(T) != 1;
- }
-
//! \return Cast data from `src` as `span<const std::uint8_t>`.
template<typename T>
span<const std::uint8_t> to_byte_span(const span<const T> src) noexcept
{
- static_assert(!has_padding<T>(), "source type may have padding");
+ static_assert(!std::is_empty<T>(), "empty value types will not work -> sizeof == 1");
+ static_assert(std::is_standard_layout<T>(), "type must have standard layout");
+ static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
+ static_assert(alignof(T) == 1, "type may have padding");
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
}
@@ -153,7 +150,9 @@ namespace epee
{
using value_type = typename T::value_type;
static_assert(!std::is_empty<value_type>(), "empty value types will not work -> sizeof == 1");
- static_assert(!has_padding<value_type>(), "source value type may have padding");
+ static_assert(std::is_standard_layout<value_type>(), "value type must have standard layout");
+ static_assert(std::is_trivially_copyable<value_type>(), "value type must be trivially copyable");
+ static_assert(alignof(value_type) == 1, "value type may have padding");
return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
}
@@ -162,7 +161,9 @@ namespace epee
span<const std::uint8_t> as_byte_span(const T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
- static_assert(!has_padding<T>(), "source type may have padding");
+ static_assert(std::is_standard_layout<T>(), "type must have standard layout");
+ static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
+ static_assert(alignof(T) == 1, "type may have padding");
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
@@ -171,7 +172,9 @@ namespace epee
span<std::uint8_t> as_mut_byte_span(T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
- static_assert(!has_padding<T>(), "source type may have padding");
+ static_assert(std::is_standard_layout<T>(), "type must have standard layout");
+ static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
+ static_assert(alignof(T) == 1, "type may have padding");
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h
index 96b0c024c..5eb9acffd 100644
--- a/contrib/epee/include/storages/portable_storage_val_converters.h
+++ b/contrib/epee/include/storages/portable_storage_val_converters.h
@@ -37,6 +37,7 @@
#include "misc_log_ex.h"
#include <boost/lexical_cast.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
#include <typeinfo>
#include <iomanip>
diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h
index 31c55b97b..8b26f49ae 100644
--- a/contrib/epee/include/string_tools.h
+++ b/contrib/epee/include/string_tools.h
@@ -71,8 +71,6 @@ namespace string_tools
std::string get_current_module_path();
#endif
void set_module_name_and_folder(const std::string& path_to_process_);
- void trim_left(std::string& str);
- void trim_right(std::string& str);
//----------------------------------------------------------------------------
inline std::string& trim(std::string& str)
{
@@ -91,6 +89,7 @@ namespace string_tools
std::string pod_to_hex(const t_pod_type& s)
{
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
+ static_assert(alignof(t_pod_type) == 1, "type may have padding");
return to_hex::string(as_byte_span(s));
}
//----------------------------------------------------------------------------
@@ -98,6 +97,8 @@ namespace string_tools
bool hex_to_pod(const boost::string_ref hex_str, t_pod_type& s)
{
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
+ static_assert(alignof(t_pod_type) == 1, "type may have padding");
+ static_assert(std::is_trivially_copyable<t_pod_type>(), "type must be trivially copyable");
return from_hex::to_buffer(as_mut_byte_span(s), hex_str);
}
//----------------------------------------------------------------------------
diff --git a/contrib/epee/src/byte_slice.cpp b/contrib/epee/src/byte_slice.cpp
index 72aa39768..47d440dff 100644
--- a/contrib/epee/src/byte_slice.cpp
+++ b/contrib/epee/src/byte_slice.cpp
@@ -152,7 +152,11 @@ namespace epee
{
std::size_t space_needed = 0;
for (const auto& source : sources)
+ {
+ if (std::numeric_limits<std::size_t>::max() - space_needed < source.size())
+ throw std::bad_alloc{};
space_needed += source.size();
+ }
if (space_needed)
{
@@ -162,9 +166,9 @@ namespace epee
for (const auto& source : sources)
{
+ assert(source.size() <= out.size()); // see check above
std::memcpy(out.data(), source.data(), source.size());
- if (out.remove_prefix(source.size()) < source.size())
- throw std::bad_alloc{}; // size_t overflow on space_needed
+ out.remove_prefix(source.size());
}
storage_ = std::move(storage);
}
diff --git a/contrib/epee/src/file_io_utils.cpp b/contrib/epee/src/file_io_utils.cpp
index c0798a510..bc592cb9f 100644
--- a/contrib/epee/src/file_io_utils.cpp
+++ b/contrib/epee/src/file_io_utils.cpp
@@ -149,40 +149,5 @@ namespace file_io_utils
}
#endif
}
-
-
- bool get_file_size(const std::string& path_to_file, uint64_t &size)
- {
-#ifdef _WIN32
- std::wstring wide_path;
- try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
- HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file_handle == INVALID_HANDLE_VALUE)
- return false;
- LARGE_INTEGER file_size;
- BOOL result = GetFileSizeEx(file_handle, &file_size);
- CloseHandle(file_handle);
- if (result) {
- size = file_size.QuadPart;
- }
- return size;
-#else
- try
- {
- std::ifstream fstream;
- fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
- size = fstream.tellg();
- fstream.close();
- return true;
- }
-
- catch(...)
- {
- return false;
- }
-#endif
- }
-
}
}
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index 4ca1a3632..46b535504 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -176,11 +176,12 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
std::vector<boost::filesystem::path> found_files;
const boost::filesystem::directory_iterator end_itr;
const boost::filesystem::path filename_base_path(filename_base);
+ const std::string filename_base_name = filename_base_path.filename().string();
const boost::filesystem::path parent_path = filename_base_path.has_parent_path() ? filename_base_path.parent_path() : ".";
for (boost::filesystem::directory_iterator iter(parent_path); iter != end_itr; ++iter)
{
- const std::string filename = iter->path().string();
- if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
+ const std::string filename = iter->path().filename().string();
+ if (filename.size() >= filename_base_name.size() && std::memcmp(filename.data(), filename_base_name.data(), filename_base_name.size()) == 0)
{
found_files.push_back(iter->path());
}
diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp
index 978572120..1e554c500 100644
--- a/contrib/epee/src/network_throttle-detail.cpp
+++ b/contrib/epee/src/network_throttle-detail.cpp
@@ -46,7 +46,7 @@
#include "misc_log_ex.h"
#include <boost/chrono.hpp>
#include "misc_language.h"
-#include <sstream>
+#include <fstream>
#include <iomanip>
#include <algorithm>
@@ -186,6 +186,23 @@ void network_throttle::handle_trafic_exact(size_t packet_size)
_handle_trafic_exact(packet_size, packet_size);
}
+namespace
+{
+ struct output_history
+ {
+ const boost::circular_buffer< network_throttle::packet_info >& history;
+ };
+
+ std::ostream& operator<<(std::ostream& out, const output_history& source)
+ {
+ out << '[';
+ for (auto sample: source.history)
+ out << sample.m_size << ' ';
+ out << ']';
+ return out;
+ }
+}
+
void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_size)
{
tick();
@@ -196,14 +213,11 @@ void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_s
m_total_packets++;
m_total_bytes += packet_size;
- std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
- std::string history_str = oss.str();
-
MTRACE("Throttle " << m_name << ": packet of ~"<<packet_size<<"b " << " (from "<<orginal_size<<" b)"
<< " Speed AVG=" << std::setw(4) << ((long int)(cts .average/1024)) <<"[w="<<cts .window<<"]"
<< " " << std::setw(4) << ((long int)(cts2.average/1024)) <<"[w="<<cts2.window<<"]"
<<" / " << " Limit="<< ((long int)(m_target_speed/1024)) <<" KiB/sec "
- << " " << history_str
+ << " " << output_history{m_history}
);
}
@@ -289,8 +303,6 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc
}
if (dbg) {
- std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
- std::string history_str = oss.str();
MTRACE((cts.delay > 0 ? "SLEEP" : "")
<< "dbg " << m_name << ": "
<< "speed is A=" << std::setw(8) <<cts.average<<" vs "
@@ -300,7 +312,7 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc
<< "E="<< std::setw(8) << E << " (Enow="<<std::setw(8)<<Enow<<") "
<< "M=" << std::setw(8) << M <<" W="<< std::setw(8) << cts.window << " "
<< "R=" << std::setw(8) << cts.recomendetDataSize << " Wgood" << std::setw(8) << Wgood << " "
- << "History: " << std::setw(8) << history_str << " "
+ << "History: " << std::setw(8) << output_history{m_history} << " "
<< "m_last_sample_time=" << std::setw(8) << m_last_sample_time
);
diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp
index cefde158c..ac68d1fdb 100644
--- a/contrib/epee/src/readline_buffer.cpp
+++ b/contrib/epee/src/readline_buffer.cpp
@@ -1,5 +1,4 @@
#include "readline_buffer.h"
-#include "string_tools.h"
#include <readline/readline.h>
#include <readline/history.h>
#include <iostream>
@@ -174,7 +173,7 @@ static void handle_line(char* line)
line_stat = rdln::full;
the_line = line;
std::string test_line = line;
- epee::string_tools::trim_right(test_line);
+ boost::trim_right(test_line);
if(!test_line.empty())
{
if (!same_as_last_line(test_line))
diff --git a/contrib/epee/src/string_tools.cpp b/contrib/epee/src/string_tools.cpp
index 4458dabdd..081cb9464 100644
--- a/contrib/epee/src/string_tools.cpp
+++ b/contrib/epee/src/string_tools.cpp
@@ -174,19 +174,6 @@ namespace string_tools
}
//----------------------------------------------------------------------------
- void trim_left(std::string& str)
- {
- boost::trim_left(str);
- return;
- }
-
- //----------------------------------------------------------------------------
- void trim_right(std::string& str)
- {
- boost::trim_right(str);
- return;
- }
-
std::string pad_string(std::string s, size_t n, char c, bool prepend)
{
if (s.size() < n)
@@ -201,13 +188,18 @@ namespace string_tools
std::string get_extension(const std::string& str)
{
- return boost::filesystem::path(str).extension().string();
+ std::string ext_with_dot = boost::filesystem::path(str).extension().string();
+
+ if (ext_with_dot.empty())
+ return {};
+
+ return ext_with_dot.erase(0, 1);
}
//----------------------------------------------------------------------------
std::string cut_off_extension(const std::string& str)
{
- return boost::filesystem::path(str).stem().string();
+ return boost::filesystem::path(str).replace_extension("").string();
}
#ifdef _WIN32
diff --git a/contrib/gitian/DOCKRUN.md b/contrib/gitian/DOCKRUN.md
index 7994d39cc..189b543da 100644
--- a/contrib/gitian/DOCKRUN.md
+++ b/contrib/gitian/DOCKRUN.md
@@ -57,7 +57,7 @@ The dockrun.sh script will do everything to build the binaries. Just specify the
version to build as its only argument, e.g.
```bash
-VERSION=v0.18.3.3
+VERSION=v0.18.3.4
./dockrun.sh $VERSION
```
diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md
index 6a97cbccb..ea3129f61 100644
--- a/contrib/gitian/README.md
+++ b/contrib/gitian/README.md
@@ -133,7 +133,7 @@ Common setup part:
su - gitianuser
GH_USER=YOUR_GITHUB_USER_NAME
-VERSION=v0.18.3.3
+VERSION=v0.18.3.4
```
Where `GH_USER` is your GitHub user name and `VERSION` is the version tag you want to build.
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index 5b7f69a56..538e4d215 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -39,6 +39,7 @@ find_package(Miniupnpc REQUIRED)
message(STATUS "Using in-tree miniupnpc")
set(UPNPC_NO_INSTALL TRUE CACHE BOOL "Disable miniupnp installation" FORCE)
+set(UPNPC_BUILD_SHARED OFF CACHE BOOL "Disable building shared library" FORCE)
add_subdirectory(miniupnp/miniupnpc)
set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
set_property(TARGET libminiupnpc-static PROPERTY POSITION_INDEPENDENT_CODE ON)
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index f80013d02..98d8c6e91 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -28,13 +28,17 @@
#include "db_lmdb.h"
#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <boost/circular_buffer.hpp>
#include <memory> // std::unique_ptr
#include <cstring> // memcpy
+#ifdef WIN32
+#include <winioctl.h>
+#endif
+
#include "string_tools.h"
-#include "file_io_utils.h"
#include "common/util.h"
#include "common/pruning.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
@@ -1321,6 +1325,54 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB()
m_hardfork = nullptr;
}
+#ifdef WIN32
+static bool disable_ntfs_compression(const boost::filesystem::path& filepath)
+{
+ DWORD file_attributes = ::GetFileAttributesW(filepath.c_str());
+ if (file_attributes == INVALID_FILE_ATTRIBUTES)
+ {
+ MERROR("Failed to get " << filepath.string() << " file attributes. Error: " << ::GetLastError());
+ return false;
+ }
+
+ if (!(file_attributes & FILE_ATTRIBUTE_COMPRESSED))
+ return true; // not compressed
+
+ LOG_PRINT_L1("Disabling NTFS compression for " << filepath.string());
+ HANDLE file_handle = ::CreateFileW(
+ filepath.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr,
+ OPEN_EXISTING,
+ boost::filesystem::is_directory(filepath) ? FILE_FLAG_BACKUP_SEMANTICS : 0, // Needed to open handles to directories
+ nullptr
+ );
+
+ if (file_handle == INVALID_HANDLE_VALUE)
+ {
+ MERROR("Failed to open handle: " << filepath.string() << ". Error: " << ::GetLastError());
+ return false;
+ }
+
+ USHORT compression_state = COMPRESSION_FORMAT_NONE;
+ DWORD bytes_returned;
+ BOOL ok = ::DeviceIoControl(
+ file_handle,
+ FSCTL_SET_COMPRESSION,
+ &compression_state,
+ sizeof(compression_state),
+ nullptr,
+ 0,
+ &bytes_returned,
+ nullptr
+ );
+
+ ::CloseHandle(file_handle);
+ return ok;
+}
+#endif
+
void BlockchainLMDB::open(const std::string& filename, const int db_flags)
{
int result;
@@ -1347,6 +1399,17 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
throw DB_ERROR("Database could not be opened");
}
+#ifdef WIN32
+ // ensure NTFS compression is disabled on the directory and database file to avoid corruption of the blockchain
+ if (!disable_ntfs_compression(filename))
+ LOG_PRINT_L0("Failed to disable NTFS compression on folder: " << filename << ". Error: " << ::GetLastError());
+ boost::filesystem::path datafile(filename);
+ datafile /= CRYPTONOTE_BLOCKCHAINDATA_FILENAME;
+ boost::filesystem::ofstream(datafile).close(); // touch the file to ensure it exists
+ if (!disable_ntfs_compression(datafile))
+ throw DB_ERROR("Database file is NTFS compressend and compression could not be disabled");
+#endif
+
boost::optional<bool> is_hdd_result = tools::is_hdd(filename.c_str());
if (is_hdd_result)
{
@@ -4500,12 +4563,11 @@ bool BlockchainLMDB::is_read_only() const
uint64_t BlockchainLMDB::get_database_size() const
{
- uint64_t size = 0;
boost::filesystem::path datafile(m_folder);
datafile /= CRYPTONOTE_BLOCKCHAINDATA_FILENAME;
- if (!epee::file_io_utils::get_file_size(datafile.string(), size))
- size = 0;
- return size;
+ boost::system::error_code ec{};
+ const boost::uintmax_t size = boost::filesystem::file_size(datafile, ec);
+ return (ec ? 0 : static_cast<uint64_t>(size));
}
void BlockchainLMDB::fixup()
diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat
index 2dc9ce3b3..2f1647ef5 100644
--- a/src/blocks/checkpoints.dat
+++ b/src/blocks/checkpoints.dat
Binary files differ
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index 07f13656b..30d8266b7 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -250,6 +250,7 @@ namespace cryptonote
ADD_CHECKPOINT2(2985000, "08f5e6b7301c1b6ed88268a28f8677a06e8ff943b3f9e48d3080f71f9c134bfb", "0x444b7b42a633c96");
ADD_CHECKPOINT2(3088000, "bddf8ca09110d33d6d497f13a113630c2b6af1c84d4f3a6f35cb1446f2604ade", "0x4aed3615c2f8c3e");
ADD_CHECKPOINT2(3102800, "083f4a34f9490403b564286e7f13fd1ed45c52c86fa47195f151594e5bc87504", "0x4bbed52d4da5dfb");
+ ADD_CHECKPOINT2(3198000, "1d685b39be51e4e84e0af69fa78e023c7cb21de7d33acd012d0371d5f78712d5", "0x517d415fee3a816");
return true;
}
diff --git a/src/common/download.cpp b/src/common/download.cpp
index 01d4a9aab..e377be266 100644
--- a/src/common/download.cpp
+++ b/src/common/download.cpp
@@ -30,7 +30,6 @@
#include <atomic>
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
-#include "file_io_utils.h"
#include "net/http_client.h"
#include "download.h"
@@ -73,8 +72,11 @@ namespace tools
{
boost::unique_lock<boost::mutex> lock(control->mutex);
std::ios_base::openmode mode = std::ios_base::out | std::ios_base::binary;
- uint64_t existing_size = 0;
- if (epee::file_io_utils::get_file_size(control->path, existing_size) && existing_size > 0)
+ boost::system::error_code ec{};
+ uint64_t existing_size = static_cast<uint64_t>(boost::filesystem::file_size(control->path, ec));
+ if (ec)
+ existing_size = 0;
+ if (existing_size > 0)
{
MINFO("Resuming downloading " << control->uri << " to " << control->path << " from " << existing_size);
mode |= std::ios_base::app;
diff --git a/src/common/password.cpp b/src/common/password.cpp
index e6dff95ea..c0edf7a78 100644
--- a/src/common/password.cpp
+++ b/src/common/password.cpp
@@ -185,7 +185,7 @@ namespace
return false;
if (verify)
{
- std::cout << "Confirm password: ";
+ std::cout << "Confirm password: " << std::flush;
if (!read_from_tty(pass2, hide_input))
return false;
if(pass1!=pass2)
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index d8cd6c6a0..ee1cac04a 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -171,7 +171,9 @@ namespace crypto {
/* Generate a value filled with random bytes.
*/
template<typename T>
- typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
+ T rand() {
+ static_assert(std::is_standard_layout<T>(), "cannot write random bytes into non-standard layout type");
+ static_assert(std::is_trivially_copyable<T>(), "cannot write random bytes into non-trivially copyable type");
typename std::remove_cv<T>::type res;
generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
return res;
@@ -314,8 +316,14 @@ namespace crypto {
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
}
- inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
- epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
+ /* Do NOT overload the << operator for crypto::secret_key here. Use secret_key_explicit_print_ref
+ * instead to prevent accidental implicit dumping of secret key material to the logs (which has
+ * happened before). For the same reason, do not overload it for crypto::ec_scalar either since
+ * crypto::secret_key is a subclass. I'm not sorry that it's obtuse; that's the point, bozo.
+ */
+ struct secret_key_explicit_print_ref { const crypto::secret_key &sk; };
+ inline std::ostream &operator <<(std::ostream &o, const secret_key_explicit_print_ref v) {
+ epee::to_hex::formatted(o, epee::as_byte_span(unwrap(unwrap(v.sk)))); return o;
}
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h
index 5a5e09f9b..3ff3619fe 100644
--- a/src/crypto/generic-ops.h
+++ b/src/crypto/generic-ops.h
@@ -33,6 +33,7 @@
#include <cstddef>
#include <cstring>
#include <functional>
+#include <memory>
#include <sodium/crypto_verify_32.h>
#define CRYPTO_MAKE_COMPARABLE(type) \
@@ -60,14 +61,18 @@ namespace crypto { \
namespace crypto { \
static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \
inline std::size_t hash_value(const type &_v) { \
- return reinterpret_cast<const std::size_t &>(_v); \
+ std::size_t h; \
+ memcpy(&h, std::addressof(_v), sizeof(h)); \
+ return h; \
} \
} \
namespace std { \
template<> \
struct hash<crypto::type> { \
std::size_t operator()(const crypto::type &_v) const { \
- return reinterpret_cast<const std::size_t &>(_v); \
+ std::size_t h; \
+ memcpy(&h, std::addressof(_v), sizeof(h)); \
+ return h; \
} \
}; \
}
diff --git a/src/cryptonote_basic/connection_context.cpp b/src/cryptonote_basic/connection_context.cpp
index 4395bad9f..642749f3c 100644
--- a/src/cryptonote_basic/connection_context.cpp
+++ b/src/cryptonote_basic/connection_context.cpp
@@ -29,6 +29,7 @@
#include "connection_context.h"
+#include <boost/optional/optional.hpp>
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "p2p/p2p_protocol_defs.h"
@@ -69,4 +70,23 @@ namespace cryptonote
};
return std::numeric_limits<size_t>::max();
}
+
+ void cryptonote_connection_context::set_state_normal()
+ {
+ m_state = state_normal;
+ m_expected_heights_start = 0;
+ m_needed_objects.clear();
+ m_needed_objects.shrink_to_fit();
+ m_expected_heights.clear();
+ m_expected_heights.shrink_to_fit();
+ m_requested_objects.clear();
+ }
+
+ boost::optional<crypto::hash> cryptonote_connection_context::get_expected_hash(const uint64_t height) const
+ {
+ const auto difference = height - m_expected_heights_start;
+ if (height < m_expected_heights_start || m_expected_heights.size() < difference)
+ return boost::none;
+ return m_expected_heights[difference];
+ }
} // cryptonote
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h
index 818999a60..db24e28fa 100644
--- a/src/cryptonote_basic/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
@@ -34,6 +34,7 @@
#include <atomic>
#include <algorithm>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/optional/optional_fwd.hpp>
#include "net/net_utils_base.h"
#include "crypto/hash.h"
@@ -42,7 +43,7 @@ namespace cryptonote
struct cryptonote_connection_context: public epee::net_utils::connection_context_base
{
cryptonote_connection_context(): m_state(state_before_handshake), m_remote_blockchain_height(0), m_last_response_height(0),
- m_last_request_time(boost::date_time::not_a_date_time), m_callback_request_count(0),
+ m_expected_heights_start(0), m_last_request_time(boost::date_time::not_a_date_time), m_callback_request_count(0),
m_last_known_hash(crypto::null_hash), m_pruning_seed(0), m_rpc_port(0), m_rpc_credits_per_hash(0), m_anchor(false), m_score(0),
m_expect_response(0), m_expect_height(0), m_num_requested(0) {}
@@ -92,11 +93,18 @@ namespace cryptonote
//! \return Maximum number of bytes permissible for `command`.
static size_t get_max_bytes(int command) noexcept;
+ //! Use this instead of `m_state = state_normal`.
+ void set_state_normal();
+
+ boost::optional<crypto::hash> get_expected_hash(uint64_t height) const;
+
state m_state;
std::vector<std::pair<crypto::hash, uint64_t>> m_needed_objects;
+ std::vector<crypto::hash> m_expected_heights;
std::unordered_set<crypto::hash> m_requested_objects;
uint64_t m_remote_blockchain_height;
uint64_t m_last_response_height;
+ uint64_t m_expected_heights_start;
boost::posix_time::ptime m_last_request_time;
copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise
crypto::hash m_last_known_hash;
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 8be23583b..e6e424c71 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -292,7 +292,7 @@ namespace cryptonote
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
if (!r)
{
- MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
+ MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", <viewkey>)");
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
}
@@ -303,7 +303,7 @@ namespace cryptonote
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
if (!r)
{
- MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
+ MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", <viewkey>)");
}
else
{
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index f9e6a6cb9..d69556acd 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -145,8 +145,8 @@
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2
#define P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT 2
-#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
-#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s
+#define P2P_DEFAULT_LIMIT_RATE_UP 8192 // kB/s
+#define P2P_DEFAULT_LIMIT_RATE_DOWN 32768 // kB/s
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour
#define P2P_IP_BLOCKTIME (60*60*24) //24 hour
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 104c26977..fd56b07c6 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -851,20 +851,12 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph
// less blocks than desired if there aren't enough.
difficulty_type Blockchain::get_difficulty_for_next_block()
{
- LOG_PRINT_L3("Blockchain::" << __func__);
-
- std::stringstream ss;
- bool print = false;
-
- int done = 0;
- ss << "get_difficulty_for_next_block: height " << m_db->height() << std::endl;
if (m_fixed_difficulty)
{
return m_db->height() ? m_fixed_difficulty : 1;
}
-start:
- difficulty_type D = 0;
+ LOG_PRINT_L3("Blockchain::" << __func__);
crypto::hash top_hash = get_tail_id();
{
@@ -873,30 +865,21 @@ start:
// something a bit out of date, but that's fine since anything which
// requires the blockchain lock will have acquired it in the first place,
// and it will be unlocked only when called from the getinfo RPC
- ss << "Locked, tail id " << top_hash << ", cached is " << m_difficulty_for_next_block_top_hash << std::endl;
if (top_hash == m_difficulty_for_next_block_top_hash)
- {
- ss << "Same, using cached diff " << m_difficulty_for_next_block << std::endl;
- D = m_difficulty_for_next_block;
- }
+ return m_difficulty_for_next_block;
}
CRITICAL_REGION_LOCAL(m_blockchain_lock);
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties;
uint64_t height;
- auto new_top_hash = get_tail_id(height); // get it again now that we have the lock
- ++height;
- if (!(new_top_hash == top_hash)) D=0;
- ss << "Re-locked, height " << height << ", tail id " << new_top_hash << (new_top_hash == top_hash ? "" : " (different)") << std::endl;
- top_hash = new_top_hash;
-
+ top_hash = get_tail_id(height); // get it again now that we have the lock
+ ++height; // top block height to blockchain height
// ND: Speedup
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
// then when the next block difficulty is queried, push the latest height data and
// pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
- bool check = false;
if (m_reset_timestamps_and_difficulties_height)
m_timestamps_and_difficulties_height = 0;
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= DIFFICULTY_BLOCKS_COUNT)
@@ -913,12 +896,8 @@ start:
m_timestamps_and_difficulties_height = height;
timestamps = m_timestamps;
difficulties = m_difficulties;
- check = true;
}
- //else
- std::vector<uint64_t> timestamps_from_cache = timestamps;
- std::vector<difficulty_type> difficulties_from_cache = difficulties;
-
+ else
{
uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(DIFFICULTY_BLOCKS_COUNT));
if (offset == 0)
@@ -931,68 +910,22 @@ start:
timestamps.reserve(height - offset);
difficulties.reserve(height - offset);
}
- ss << "Looking up " << (height - offset) << " from " << offset << std::endl;
for (; offset < height; offset++)
{
timestamps.push_back(m_db->get_block_timestamp(offset));
difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
}
- if (check) if (timestamps != timestamps_from_cache || difficulties !=difficulties_from_cache)
- {
- ss << "Inconsistency XXX:" << std::endl;
- ss << "top hash: "<<top_hash << std::endl;
- ss << "timestamps: " << timestamps_from_cache.size() << " from cache, but " << timestamps.size() << " without" << std::endl;
- ss << "difficulties: " << difficulties_from_cache.size() << " from cache, but " << difficulties.size() << " without" << std::endl;
- ss << "timestamps_from_cache:" << std::endl; for (const auto &v :timestamps_from_cache) ss << " " << v << std::endl;
- ss << "timestamps:" << std::endl; for (const auto &v :timestamps) ss << " " << v << std::endl;
- ss << "difficulties_from_cache:" << std::endl; for (const auto &v :difficulties_from_cache) ss << " " << v << std::endl;
- ss << "difficulties:" << std::endl; for (const auto &v :difficulties) ss << " " << v << std::endl;
-
- uint64_t dbh = m_db->height();
- uint64_t sh = dbh < 10000 ? 0 : dbh - 10000;
- ss << "History from -10k at :" << dbh << ", from " << sh << std::endl;
- for (uint64_t h = sh; h < dbh; ++h)
- {
- uint64_t ts = m_db->get_block_timestamp(h);
- difficulty_type d = m_db->get_block_cumulative_difficulty(h);
- ss << " " << h << " " << ts << " " << d << std::endl;
- }
- print = true;
- }
m_timestamps_and_difficulties_height = height;
m_timestamps = timestamps;
m_difficulties = difficulties;
}
-
size_t target = get_difficulty_target();
difficulty_type diff = next_difficulty(timestamps, difficulties, target);
CRITICAL_REGION_LOCAL1(m_difficulty_lock);
m_difficulty_for_next_block_top_hash = top_hash;
m_difficulty_for_next_block = diff;
- if (D && D != diff)
- {
- ss << "XXX Mismatch at " << height << "/" << top_hash << "/" << get_tail_id() << ": cached " << D << ", real " << diff << std::endl;
- print = true;
- }
-
- ++done;
- if (done == 1 && D && D != diff)
- {
- print = true;
- ss << "Might be a race. Let's see what happens if we try again..." << std::endl;
- epee::misc_utils::sleep_no_w(100);
- goto start;
- }
- ss << "Diff for " << top_hash << ": " << diff << std::endl;
- if (print)
- {
- MGINFO("START DUMP");
- MGINFO(ss.str());
- MGINFO("END DUMP");
- MGINFO("Please send moneromooo on Libera.Chat the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
- }
return diff;
}
//------------------------------------------------------------------
@@ -1210,12 +1143,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
// just the latter (because the rollback was done above).
rollback_blockchain_switching(disconnected_chain, split_height);
- // FIXME: Why do we keep invalid blocks around? Possibly in case we hear
- // about them again so we can immediately dismiss them, but needs some
- // looking into.
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
- add_block_as_invalid(bei, blkid);
- MERROR("The block was inserted as invalid while connecting new alternative chain, block_id: " << blkid);
m_db->remove_alt_block(blkid);
alt_ch_iter++;
@@ -1223,7 +1151,6 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
{
const auto &bei = *alt_ch_to_orph_iter++;
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
- add_block_as_invalid(bei, blkid);
m_db->remove_alt_block(blkid);
}
return false;
@@ -2363,17 +2290,8 @@ void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint
bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) const
{
// rct outputs don't exist before v4
- if (amount == 0)
- {
- switch (m_nettype)
- {
- case STAGENET: start_height = stagenet_hard_forks[3].height; break;
- case TESTNET: start_height = testnet_hard_forks[3].height; break;
- case MAINNET: start_height = mainnet_hard_forks[3].height; break;
- case FAKECHAIN: start_height = 0; break;
- default: return false;
- }
- }
+ if (amount == 0 && m_nettype != network_type::FAKECHAIN)
+ start_height = m_hardfork->get_earliest_ideal_height_for_version(HF_VERSION_DYNAMIC_FEE);
else
start_height = 0;
base = 0;
@@ -5552,7 +5470,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
-static const char expected_block_hashes_hash[] = "0046a0019beb6e697e27d834d6127851425f7ee09bfb8e9f8df7b1420131aca8";
+static const char expected_block_hashes_hash[] = "8ada865350270fd008397684d978dac75ea4029a8a1ffcaa9975c43be119ec19";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index dc9d6612f..8f044154b 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -144,7 +144,7 @@ namespace cryptonote
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
- CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
+ CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{txkey.sec} << ")");
r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")");
@@ -484,7 +484,7 @@ namespace cryptonote
crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
ss_ring_s << "signatures:" << ENDL;
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
- ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output << ENDL;
+ ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << crypto::secret_key_explicit_print_ref{in_contexts[i].in_ephemeral.sec} << ENDL << "real_output: " << src_entr.real_output << ENDL;
i++;
}
diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp
index 4e65eafa4..f8962df06 100644
--- a/src/cryptonote_protocol/block_queue.cpp
+++ b/src/cryptonote_protocol/block_queue.cpp
@@ -40,15 +40,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "cn.block_queue"
-namespace std {
- static_assert(sizeof(size_t) <= sizeof(boost::uuids::uuid), "boost::uuids::uuid too small");
- template<> struct hash<boost::uuids::uuid> {
- std::size_t operator()(const boost::uuids::uuid &_v) const {
- return reinterpret_cast<const std::size_t &>(_v);
- }
- };
-}
-
namespace cryptonote
{
@@ -60,10 +51,10 @@ void block_queue::add_blocks(uint64_t height, std::vector<cryptonote::block_comp
blocks.insert(span(height, std::move(bcel), connection_id, addr, rate, size));
if (has_hashes)
{
- for (const crypto::hash &h: hashes)
+ for (std::size_t i = 0; i < hashes.size(); ++i)
{
- requested_hashes.insert(h);
- have_blocks.insert(h);
+ requested_hashes.insert(hashes[i]);
+ have_blocks.emplace(hashes[i], height + i);
}
set_span_hashes(height, connection_id, hashes);
}
@@ -228,6 +219,16 @@ bool block_queue::have(const crypto::hash &hash) const
return have_blocks.find(hash) != have_blocks.end();
}
+std::uint64_t block_queue::have_height(const crypto::hash &hash) const
+{
+ boost::unique_lock<boost::recursive_mutex> lock(mutex);
+ const auto elem = have_blocks.find(hash);
+ if (elem == have_blocks.end())
+ return std::numeric_limits<std::uint64_t>::max();
+ return elem->second;
+}
+
+
std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, bool sync_pruned_blocks, uint32_t local_pruning_seed, uint32_t pruning_seed, uint64_t blockchain_height, const std::vector<std::pair<crypto::hash, uint64_t>> &block_hashes, boost::posix_time::ptime time)
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
@@ -472,7 +473,7 @@ bool block_queue::has_spans(const boost::uuids::uuid &connection_id) const
float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
- std::unordered_map<boost::uuids::uuid, float> speeds;
+ std::unordered_map<boost::uuids::uuid, float, boost::hash<boost::uuids::uuid>> speeds;
for (const auto &span: blocks)
{
if (span.blocks.empty())
@@ -480,7 +481,7 @@ float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
// note that the average below does not average over the whole set, but over the
// previous pseudo average and the latest rate: this gives much more importance
// to the latest measurements, which is fine here
- std::unordered_map<boost::uuids::uuid, float>::iterator i = speeds.find(span.connection_id);
+ const auto i = speeds.find(span.connection_id);
if (i == speeds.end())
speeds.insert(std::make_pair(span.connection_id, span.rate));
else
diff --git a/src/cryptonote_protocol/block_queue.h b/src/cryptonote_protocol/block_queue.h
index 64ff106a3..df64948fa 100644
--- a/src/cryptonote_protocol/block_queue.h
+++ b/src/cryptonote_protocol/block_queue.h
@@ -98,6 +98,7 @@ namespace cryptonote
bool foreach(std::function<bool(const span&)> f) const;
bool requested(const crypto::hash &hash) const;
bool have(const crypto::hash &hash) const;
+ std::uint64_t have_height(const crypto::hash &hash) const;
private:
void erase_block(block_map::iterator j);
@@ -107,6 +108,6 @@ namespace cryptonote
block_map blocks;
mutable boost::recursive_mutex mutex;
std::unordered_set<crypto::hash> requested_hashes;
- std::unordered_set<crypto::hash> have_blocks;
+ std::unordered_map<crypto::hash, std::uint64_t> have_blocks;
};
}
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 515b78c94..b003341e8 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -157,6 +157,7 @@ namespace cryptonote
bool should_ask_for_pruned_data(cryptonote_connection_context& context, uint64_t first_block_height, uint64_t nblocks, bool check_block_weights) const;
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
void drop_connection_with_score(cryptonote_connection_context &context, unsigned int score, bool flush_all_spans);
+ void drop_connection(const boost::uuids::uuid&);
void drop_connections(const epee::net_utils::network_address address);
bool kick_idle_peers();
bool check_standby_peers();
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index ef437bdf6..ff9c7e5a1 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -35,6 +35,7 @@
// (may contain code and/or modifications by other developers)
// developer rfree: this code is caller of our new network code, and is modded; e.g. for rate limiting
+#include <boost/optional/optional.hpp>
#include <list>
#include <ctime>
@@ -380,7 +381,7 @@ namespace cryptonote
if(m_core.have_block(hshd.top_id))
{
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
if(is_inital && hshd.current_height >= target && target == m_core.get_current_blockchain_height())
on_connection_synchronized();
return true;
@@ -389,7 +390,7 @@ namespace cryptonote
// No chain synchronization over hidden networks (tor, i2p, etc.)
if(context.m_remote_address.get_zone() != epee::net_utils::zone::public_)
{
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
return true;
}
@@ -430,7 +431,7 @@ namespace cryptonote
if (m_no_sync)
{
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
return true;
}
@@ -1198,8 +1199,9 @@ namespace cryptonote
block_hashes.reserve(arg.blocks.size());
const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
uint64_t start_height = std::numeric_limits<uint64_t>::max();
+ crypto::hash previous{};
cryptonote::block b;
- for(const block_complete_entry& block_entry: arg.blocks)
+ for(std::size_t i = 0; i < arg.blocks.size(); ++i)
{
if (m_stopping)
{
@@ -1207,10 +1209,10 @@ namespace cryptonote
}
crypto::hash block_hash;
- if(!parse_and_validate_block_from_blob(block_entry.block, b, block_hash))
+ if(!parse_and_validate_block_from_blob(arg.blocks[i].block, b, block_hash))
{
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: "
- << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection");
+ << epee::string_tools::buff_to_hex_nodelimer(arg.blocks[i].block) << ", dropping connection");
drop_connection(context, false, false);
++m_sync_bad_spans_downloaded;
return 1;
@@ -1218,14 +1220,25 @@ namespace cryptonote
if (b.miner_tx.vin.size() != 1 || b.miner_tx.vin.front().type() != typeid(txin_gen))
{
LOG_ERROR_CCONTEXT("sent wrong block: block: miner tx does not have exactly one txin_gen input"
- << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection");
+ << epee::string_tools::buff_to_hex_nodelimer(arg.blocks[i].block) << ", dropping connection");
drop_connection(context, false, false);
++m_sync_bad_spans_downloaded;
return 1;
}
+
+ const auto this_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height;
+ if (context.get_expected_hash(this_height) != block_hash)
+ {
+ LOG_ERROR_CCONTEXT("Sent invalid chain");
+ drop_connection(context, false, false);
+ ++m_sync_bad_spans_downloaded;
+ return 1;
+ }
+
+ // if first block
if (start_height == std::numeric_limits<uint64_t>::max())
{
- start_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height;
+ start_height = this_height;
if (start_height > context.m_expect_height)
{
LOG_ERROR_CCONTEXT("sent block ahead of expected height, dropping connection");
@@ -1233,21 +1246,45 @@ namespace cryptonote
++m_sync_bad_spans_downloaded;
return 1;
}
+
+ if (this_height == 0 || context.get_expected_hash(this_height - 1) != b.prev_id)
+ {
+ LOG_ERROR_CCONTEXT("Sent invalid chain");
+ drop_connection(context, false, false);
+ ++m_sync_bad_spans_downloaded;
+ return 1;
+ }
+ }
+ else if (b.prev_id != previous)
+ {
+ LOG_ERROR_CCONTEXT("Sent invalid chain");
+ drop_connection(context, false, false);
+ ++m_sync_bad_spans_downloaded;
+ return 1;
+ }
+ previous = block_hash;
+
+ if (start_height + i != this_height)
+ {
+ LOG_ERROR_CCONTEXT("Sent invalid chain");
+ drop_connection(context, false, false);
+ ++m_sync_bad_spans_downloaded;
+ return 1;
}
auto req_it = context.m_requested_objects.find(block_hash);
if(req_it == context.m_requested_objects.end())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(arg.blocks[i].block))
<< " wasn't requested, dropping connection");
drop_connection(context, false, false);
++m_sync_bad_spans_downloaded;
return 1;
}
- if(b.tx_hashes.size() != block_entry.txs.size())
+ if(b.tx_hashes.size() != arg.blocks[i].txs.size())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
- << ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(arg.blocks[i].block))
+ << ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << arg.blocks[i].txs.size() << ", dropping connection");
drop_connection(context, false, false);
++m_sync_bad_spans_downloaded;
return 1;
@@ -1465,6 +1502,14 @@ namespace cryptonote
bool parent_known = m_core.have_block(new_block.prev_id);
if (!parent_known)
{
+ const std::uint64_t confirmed_height = m_block_queue.have_height(new_block.prev_id);
+ if (confirmed_height != std::numeric_limits<std::uint64_t>::max() && confirmed_height + 1 != start_height)
+ {
+ MERROR(context << "Found incorrect height for " << new_block.prev_id << " provided by " << span_connection_id);
+ drop_connection(span_connection_id);
+ return 1;
+ }
+
// it could be:
// - later in the current chain
// - later in an alt chain
@@ -2093,7 +2138,6 @@ skip:
m_block_queue.flush_stale_spans(live_connections);
// if we don't need to get next span, and the block queue is full enough, wait a bit
- bool start_from_current_chain = false;
if (!force_next_span)
{
do
@@ -2116,7 +2160,7 @@ skip:
return false;
}
MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done");
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
on_connection_synchronized();
return true;
@@ -2265,7 +2309,7 @@ skip:
return false;
}
MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done");
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
on_connection_synchronized();
return true;
@@ -2378,7 +2422,7 @@ skip:
const uint64_t blockchain_height = m_core.get_current_blockchain_height();
if (std::max(blockchain_height, m_block_queue.get_next_needed_height(blockchain_height)) >= m_core.get_target_blockchain_height())
{
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
MLOG_PEER_STATE("Nothing to do for now, switching to normal state");
return true;
}
@@ -2421,14 +2465,11 @@ skip:
m_core.get_short_chain_history(r.block_ids);
CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty");
- if (!start_from_current_chain)
+ // we'll want to start off from where we are on that peer, which may not be added yet
+ if (context.m_last_known_hash != crypto::null_hash && r.block_ids.front() != context.m_last_known_hash)
{
- // we'll want to start off from where we are on that peer, which may not be added yet
- if (context.m_last_known_hash != crypto::null_hash && r.block_ids.front() != context.m_last_known_hash)
- {
- context.m_expect_height = std::numeric_limits<uint64_t>::max();
- r.block_ids.push_front(context.m_last_known_hash);
- }
+ context.m_expect_height = std::numeric_limits<uint64_t>::max();
+ r.block_ids.push_front(context.m_last_known_hash);
}
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
@@ -2441,7 +2482,7 @@ skip:
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
- MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() << ", start_from_current_chain " << start_from_current_chain);
+ MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size());
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
MLOG_PEER_STATE("requesting chain");
}else
@@ -2455,7 +2496,7 @@ skip:
<< "\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
<< "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]");
- context.m_state = cryptonote_connection_context::state_normal;
+ context.set_state_normal();
if (context.m_remote_blockchain_height >= m_core.get_target_blockchain_height())
{
if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
@@ -2628,11 +2669,14 @@ skip:
return 1;
}
+ context.m_expected_heights_start = arg.start_height;
+
+ context.m_expected_heights.clear();
+ context.m_expected_heights.reserve(arg.m_block_ids.size());
context.m_needed_objects.clear();
context.m_needed_objects.reserve(arg.m_block_ids.size());
uint64_t added = 0;
std::unordered_set<crypto::hash> blocks_found;
- bool first = true;
bool expect_unknown = false;
for (size_t i = 0; i < arg.m_block_ids.size(); ++i)
{
@@ -2644,9 +2688,10 @@ skip:
}
int where;
const bool have_block = m_core.have_block_unlocked(arg.m_block_ids[i], &where);
- if (first)
+ if (i == 0)
{
- if (!have_block && !m_block_queue.requested(arg.m_block_ids[i]) && !m_block_queue.have(arg.m_block_ids[i]))
+ // our outgoing chainlist only has proven blocks (i.e. downloaded)
+ if (!have_block && m_block_queue.have_height(arg.m_block_ids[i]) != arg.start_height)
{
LOG_ERROR_CCONTEXT("First block hash is unknown, dropping connection");
drop_connection_with_score(context, 5, false);
@@ -2655,7 +2700,7 @@ skip:
if (!have_block)
expect_unknown = true;
}
- if (!first)
+ if (0 < i)
{
// after the first, blocks may be known or unknown, but if they are known,
// they should be at the same height if on the main chain
@@ -2696,10 +2741,10 @@ skip:
expect_unknown = true;
}
const uint64_t block_weight = arg.m_block_weights.empty() ? 0 : arg.m_block_weights[i];
+ context.m_expected_heights.push_back(arg.m_block_ids[i]);
context.m_needed_objects.push_back(std::make_pair(arg.m_block_ids[i], block_weight));
if (++added == n_use_blocks)
break;
- first = false;
}
context.m_last_response_height -= arg.m_block_ids.size() - n_use_blocks;
@@ -2908,6 +2953,16 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
+ void t_cryptonote_protocol_handler<t_core>::drop_connection(const boost::uuids::uuid& id)
+ {
+ m_p2p->for_connection(id, [this](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
+ // This _could be_ outside of strand, so careful on actions
+ drop_connection(context, true, false);
+ return true;
+ });
+ }
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
void t_cryptonote_protocol_handler<t_core>::drop_connections(const epee::net_utils::network_address address)
{
MWARNING("dropping connections to " << address.str());
@@ -2924,6 +2979,7 @@ skip:
{
m_block_queue.flush_spans(id, true);
m_p2p->for_connection(id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
+ // This _could be_ outside of strand, so careful on actions
drop_connection(context, true, false);
return true;
});
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 92034a435..378123c7d 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -396,6 +396,8 @@ namespace levin
for (auto& connection : connections)
{
std::sort(connection.first.begin(), connection.first.end()); // don't leak receive order
+ connection.first.erase(std::unique(connection.first.begin(), connection.first.end()),
+ connection.first.end());
make_payload_send_txs(*zone_->p2p, std::move(connection.first), connection.second, zone_->pad_txs, true);
}
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 20c906141..087a4e48b 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -696,6 +696,16 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
std::ifstream ifs(ban_list_path.string());
for (std::string line; std::getline(ifs, line); )
{
+ // ignore comments after '#' character
+ const size_t pound_idx = line.find('#');
+ if (pound_idx != std::string::npos)
+ line.resize(pound_idx);
+
+ // trim whitespace and ignore empty lines
+ boost::trim(line);
+ if (line.empty())
+ continue;
+
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index d70ece229..c770a6e22 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -317,13 +317,15 @@ namespace hw {
{
// sending change to yourself; derivation = a*R
r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", <viewkey>)");
}
else
{
// sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
- r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
+ const crypto::secret_key &tx_privkey{dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key};
+ r = generate_key_derivation(dst_entr.addr.m_view_public_key, tx_privkey, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation("
+ << dst_entr.addr.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{tx_privkey} << ")");
}
if (need_additional_txkeys)
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index a4b5f3ef0..5d0afe1ee 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -527,6 +527,7 @@ namespace hw {
{0x2c97, 0x0004, 0, 0xffa0},
{0x2c97, 0x0005, 0, 0xffa0},
{0x2c97, 0x0006, 0, 0xffa0},
+ {0x2c97, 0x0007, 0, 0xffa0},
};
bool device_ledger::connect(void) {
diff --git a/src/lmdb/key_stream.h b/src/lmdb/key_stream.h
index 11fa284dd..74cb536e5 100644
--- a/src/lmdb/key_stream.h
+++ b/src/lmdb/key_stream.h
@@ -133,6 +133,7 @@ namespace lmdb
//! \pre `!is_end()` \return Current key
K get_key() const noexcept
{
+ static_assert(std::is_trivially_copyable<K>(), "key is not memcpy safe");
assert(!is_end());
K out;
std::memcpy(std::addressof(out), key.data(), sizeof(out));
diff --git a/src/lmdb/table.h b/src/lmdb/table.h
index 4ded4ba54..48b94bc66 100644
--- a/src/lmdb/table.h
+++ b/src/lmdb/table.h
@@ -55,7 +55,7 @@ namespace lmdb
static expect<F> get_value(MDB_val value) noexcept
{
static_assert(std::is_same<U, V>(), "bad MONERO_FIELD?");
- static_assert(std::is_pod<F>(), "F must be POD");
+ static_assert(std::is_trivially_copyable<F>(), "F must be memcpy safe");
static_assert(sizeof(F) + offset <= sizeof(U), "bad field type and/or offset");
if (value.mv_size != sizeof(U))
diff --git a/src/lmdb/util.h b/src/lmdb/util.h
index c6c75bc00..038411417 100644
--- a/src/lmdb/util.h
+++ b/src/lmdb/util.h
@@ -111,6 +111,7 @@ namespace lmdb
template<typename T, std::size_t offset = 0>
inline int less(MDB_val const* left, MDB_val const* right) noexcept
{
+ static_assert(std::is_trivially_copyable<T>(), "memcpy will not work");
if (!left || !right || left->mv_size < sizeof(T) + offset || right->mv_size < sizeof(T) + offset)
{
assert("invalid use of custom comparison" == 0);
@@ -127,7 +128,7 @@ namespace lmdb
/*!
A LMDB comparison function that uses `std::memcmp`.
- \toaram T is `!epee::has_padding`
+ \toaram T has standard layout and an alignment of 1
\tparam offset to `T` within the value.
\return The result of `std::memcmp` over the value.
@@ -135,7 +136,7 @@ namespace lmdb
template<typename T, std::size_t offset = 0>
inline int compare(MDB_val const* left, MDB_val const* right) noexcept
{
- static_assert(!epee::has_padding<T>(), "memcmp will not work");
+ static_assert(std::is_standard_layout<T>() && alignof(T) == 1, "memcmp will not work");
if (!left || !right || left->mv_size < sizeof(T) + offset || right->mv_size < sizeof(T) + offset)
{
assert("invalid use of custom comparison" == 0);
diff --git a/src/lmdb/value_stream.h b/src/lmdb/value_stream.h
index bd2814ef4..2475ec191 100644
--- a/src/lmdb/value_stream.h
+++ b/src/lmdb/value_stream.h
@@ -162,8 +162,8 @@ namespace lmdb
G get_value() const noexcept
{
static_assert(std::is_same<U, T>(), "bad MONERO_FIELD usage?");
- static_assert(std::is_pod<U>(), "value type must be pod");
- static_assert(std::is_pod<G>(), "field type must be pod");
+ static_assert(std::is_trivially_copyable<U>(), "value type must be memcpy safe");
+ static_assert(std::is_trivially_copyable<G>(), "field type must be memcpy safe");
static_assert(sizeof(G) + uoffset <= sizeof(U), "bad field and/or offset");
assert(sizeof(G) + uoffset <= values.size());
assert(!is_end());
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 98d8ecfff..cbdeef7e3 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -125,7 +125,8 @@ namespace nodetool
template<class t_payload_net_handler>
class node_server: public epee::levin::levin_commands_handler<p2p_connection_context_t<typename t_payload_net_handler::connection_context> >,
public i_p2p_endpoint<typename t_payload_net_handler::connection_context>,
- public epee::net_utils::i_connection_filter
+ public epee::net_utils::i_connection_filter,
+ public epee::net_utils::i_connection_limit
{
struct by_conn_id{};
struct by_peer_id{};
@@ -351,7 +352,10 @@ namespace nodetool
virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score = 1);
//----------------- i_connection_filter --------------------------------------------------------
virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL);
+ //----------------- i_connection_limit ---------------------------------------------------------
+ virtual bool is_host_limit(const epee::net_utils::network_address &address);
//-----------------------------------------------------------------------------------------------
+
bool parse_peer_from_string(epee::net_utils::network_address& pe, const std::string& node_addr, uint16_t default_port = 0);
bool handle_command_line(
const boost::program_options::variables_map& vm
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 71f5393e8..e1a1db9a8 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -228,6 +228,26 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::is_host_limit(const epee::net_utils::network_address &address)
+ {
+ const network_zone& zone = m_network_zones.at(address.get_zone());
+ if (zone.m_current_number_of_in_peers >= zone.m_config.m_net_config.max_in_connection_count) // in peers limit
+ {
+ MWARNING("Exceeded max incoming connections, so dropping this one.");
+ return true;
+ }
+
+ if(has_too_many_connections(address))
+ {
+ MWARNING("CONNECTION FROM " << address.host_str() << " REFUSED, too many connections from the same address");
+ return true;
+ }
+
+ return false;
+ }
+
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds, bool add_only)
{
if(!addr.is_blockable())
@@ -531,6 +551,16 @@ namespace nodetool
std::istringstream iss(banned_ips);
for (std::string line; std::getline(iss, line); )
{
+ // ignore comments after '#' character
+ const size_t pound_idx = line.find('#');
+ if (pound_idx != std::string::npos)
+ line.resize(pound_idx);
+
+ // trim whitespace and ignore empty lines
+ boost::trim(line);
+ if (line.empty())
+ continue;
+
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{
@@ -709,7 +739,7 @@ namespace nodetool
full_addrs.insert("51.79.173.165:28080");
full_addrs.insert("192.99.8.110:28080");
full_addrs.insert("37.187.74.171:28080");
- full_addrs.insert("77.172.183.193:28080");
+ full_addrs.insert("88.99.195.15:28080");
}
else if (m_nettype == cryptonote::STAGENET)
{
@@ -717,7 +747,7 @@ namespace nodetool
full_addrs.insert("51.79.173.165:38080");
full_addrs.insert("192.99.8.110:38080");
full_addrs.insert("37.187.74.171:38080");
- full_addrs.insert("77.172.183.193:38080");
+ full_addrs.insert("88.99.195.15:38080");
}
else if (m_nettype == cryptonote::FAKECHAIN)
{
@@ -730,7 +760,7 @@ namespace nodetool
full_addrs.insert("51.79.173.165:18080");
full_addrs.insert("192.99.8.110:18080");
full_addrs.insert("37.187.74.171:18080");
- full_addrs.insert("77.172.183.193:18080");
+ full_addrs.insert("88.99.195.15:18080");
}
return full_addrs;
}
@@ -971,6 +1001,7 @@ namespace nodetool
std::string ipv6_addr = "";
std::string ipv6_port = "";
zone.second.m_net_server.set_connection_filter(this);
+ zone.second.m_net_server.set_connection_limit(this);
MINFO("Binding (IPv4) on " << zone.second.m_bind_ip << ":" << zone.second.m_port);
if (!zone.second.m_bind_ipv6_address.empty() && m_use_ipv6)
{
@@ -2483,6 +2514,20 @@ namespace nodetool
std::vector<peerlist_entry> local_peerlist_new;
zone.m_peerlist.get_peerlist_head(local_peerlist_new, true, max_peerlist_size);
+ /* Tor/I2P nodes receiving connections via forwarding (from tor/i2p daemon)
+ do not know the address of the connecting peer. This is relayed to them,
+ iff the node has setup an inbound hidden service.
+
+ \note Insert into `local_peerlist_new` so that it is only sent once like
+ the other peers. */
+ if(outgoing_to_same_zone)
+ {
+ local_peerlist_new.insert(
+ local_peerlist_new.begin() + crypto::rand_range(std::size_t(0), local_peerlist_new.size()),
+ peerlist_entry{zone.m_our_address, zone.m_config.m_peer_id, 0}
+ );
+ }
+
//only include out peers we did not already send
rsp.local_peerlist_new.reserve(local_peerlist_new.size());
for (auto &pe: local_peerlist_new)
@@ -2493,17 +2538,6 @@ namespace nodetool
}
m_payload_handler.get_payload_sync_data(rsp.payload_data);
- /* Tor/I2P nodes receiving connections via forwarding (from tor/i2p daemon)
- do not know the address of the connecting peer. This is relayed to them,
- iff the node has setup an inbound hidden service. The other peer will have
- to use the random peer_id value to link the two. My initial thought is that
- the inbound peer should leave the other side marked as `<unknown tor host>`,
- etc., because someone could give faulty addresses over Tor/I2P to get the
- real peer with that identity banned/blacklisted. */
-
- if(outgoing_to_same_zone)
- rsp.local_peerlist_new.push_back(peerlist_entry{zone.m_our_address, zone.m_config.m_peer_id, std::time(nullptr)});
-
LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC");
return 1;
}
@@ -2547,13 +2581,6 @@ namespace nodetool
return 1;
}
- if (zone.m_current_number_of_in_peers >= zone.m_config.m_net_config.max_in_connection_count) // in peers limit
- {
- LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but already have max incoming connections, so dropping this one.");
- drop_connection(context);
- return 1;
- }
-
if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, true))
{
LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but process_payload_sync_data returned false, dropping connection.");
@@ -2563,13 +2590,6 @@ namespace nodetool
zone.m_notifier.on_handshake_complete(context.m_connection_id, context.m_is_income);
- if(has_too_many_connections(context.m_remote_address))
- {
- LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << context.m_remote_address.host_str() << " REFUSED, too many connections from the same address");
- drop_connection(context);
- return 1;
- }
-
//associate peer_id with this connection
context.peer_id = arg.node_data.peer_id;
context.m_in_timedsync = false;
@@ -2889,15 +2909,16 @@ namespace nodetool
if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) {
count++;
- if (count > max_connections) {
+ // the only call location happens BEFORE foreach_connection list is updated
+ if (count >= max_connections) {
return false;
}
}
return true;
});
-
- return count > max_connections;
+ // the only call location happens BEFORE foreach_connection list is updated
+ return count >= max_connections;
}
template<class t_payload_net_handler>
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 0ad80f41e..1b0e3f261 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -2808,6 +2808,12 @@ namespace cryptonote
}
else
{
+ if (!i->ip)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "No ip/host supplied";
+ return false;
+ }
na = epee::net_utils::ipv4_network_address{i->ip, 0};
}
if (i->ban)
diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index 11ab80666..b13663ac9 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -520,6 +520,8 @@ namespace rpc
res.info.target_height = res.info.height;
}
+ m_core.get_blockchain_top(res.info.top_block_height, res.info.top_block_hash);
+
auto& chain = m_core.get_blockchain_storage();
res.info.wide_difficulty = chain.get_difficulty_for_next_block();
diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h
index dd9d198ed..7f3b787b6 100644
--- a/src/rpc/message_data_structs.h
+++ b/src/rpc/message_data_structs.h
@@ -176,6 +176,7 @@ namespace rpc
{
uint64_t height;
uint64_t target_height;
+ uint64_t top_block_height;
cryptonote::difficulty_type wide_difficulty;
uint64_t difficulty;
uint64_t target;
diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp
index 43d9cfebe..8580f93b8 100644
--- a/src/serialization/json_object.cpp
+++ b/src/serialization/json_object.cpp
@@ -273,7 +273,10 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t
{
INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures);
}
- INSERT_INTO_JSON_OBJECT(dest, ringct, tx.rct_signatures);
+ {
+ dest.Key("ringct");
+ toJsonValue(dest, tx.rct_signatures, tx.pruned);
+ }
dest.EndObject();
}
@@ -1111,7 +1114,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResp
GET_FROM_JSON_OBJECT(val, response.reward, reward);
}
-void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, const bool prune)
{
using boost::adaptors::transform;
@@ -1131,7 +1134,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig&
}
// prunable
- if (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty())
+ if (!prune && (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()))
{
dest.Key("prunable");
dest.StartObject();
@@ -1423,9 +1426,14 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::r
{
dest.StartObject();
+ const uint64_t difficulty_top64 = (info.wide_difficulty >> 64).convert_to<std::uint64_t>();
+ const uint64_t cumulative_difficulty_top64 = (info.wide_cumulative_difficulty >> 64).convert_to<std::uint64_t>();
+
INSERT_INTO_JSON_OBJECT(dest, height, info.height);
INSERT_INTO_JSON_OBJECT(dest, target_height, info.target_height);
+ INSERT_INTO_JSON_OBJECT(dest, top_block_height, info.top_block_height);
INSERT_INTO_JSON_OBJECT(dest, difficulty, info.difficulty);
+ INSERT_INTO_JSON_OBJECT(dest, difficulty_top64, difficulty_top64);
INSERT_INTO_JSON_OBJECT(dest, target, info.target);
INSERT_INTO_JSON_OBJECT(dest, tx_count, info.tx_count);
INSERT_INTO_JSON_OBJECT(dest, tx_pool_size, info.tx_pool_size);
@@ -1440,12 +1448,14 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::r
INSERT_INTO_JSON_OBJECT(dest, nettype, info.nettype);
INSERT_INTO_JSON_OBJECT(dest, top_block_hash, info.top_block_hash);
INSERT_INTO_JSON_OBJECT(dest, cumulative_difficulty, info.cumulative_difficulty);
+ INSERT_INTO_JSON_OBJECT(dest, cumulative_difficulty_top64, cumulative_difficulty_top64);
INSERT_INTO_JSON_OBJECT(dest, block_size_limit, info.block_size_limit);
INSERT_INTO_JSON_OBJECT(dest, block_weight_limit, info.block_weight_limit);
INSERT_INTO_JSON_OBJECT(dest, block_size_median, info.block_size_median);
INSERT_INTO_JSON_OBJECT(dest, block_weight_median, info.block_weight_median);
INSERT_INTO_JSON_OBJECT(dest, adjusted_time, info.adjusted_time);
INSERT_INTO_JSON_OBJECT(dest, start_time, info.start_time);
+ INSERT_INTO_JSON_OBJECT(dest, version, info.version);
dest.EndObject();
}
@@ -1457,9 +1467,14 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf
throw WRONG_TYPE("json object");
}
+ uint64_t difficulty_top64 = 0;
+ uint64_t cumulative_difficulty_top64 = 0;
+
GET_FROM_JSON_OBJECT(val, info.height, height);
GET_FROM_JSON_OBJECT(val, info.target_height, target_height);
+ GET_FROM_JSON_OBJECT(val, info.top_block_height, top_block_height);
GET_FROM_JSON_OBJECT(val, info.difficulty, difficulty);
+ GET_FROM_JSON_OBJECT(val, difficulty_top64, difficulty_top64);
GET_FROM_JSON_OBJECT(val, info.target, target);
GET_FROM_JSON_OBJECT(val, info.tx_count, tx_count);
GET_FROM_JSON_OBJECT(val, info.tx_pool_size, tx_pool_size);
@@ -1474,12 +1489,22 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf
GET_FROM_JSON_OBJECT(val, info.nettype, nettype);
GET_FROM_JSON_OBJECT(val, info.top_block_hash, top_block_hash);
GET_FROM_JSON_OBJECT(val, info.cumulative_difficulty, cumulative_difficulty);
+ GET_FROM_JSON_OBJECT(val, cumulative_difficulty_top64, cumulative_difficulty_top64);
GET_FROM_JSON_OBJECT(val, info.block_size_limit, block_size_limit);
GET_FROM_JSON_OBJECT(val, info.block_weight_limit, block_weight_limit);
GET_FROM_JSON_OBJECT(val, info.block_size_median, block_size_median);
GET_FROM_JSON_OBJECT(val, info.block_weight_median, block_weight_median);
GET_FROM_JSON_OBJECT(val, info.adjusted_time, adjusted_time);
GET_FROM_JSON_OBJECT(val, info.start_time, start_time);
+ GET_FROM_JSON_OBJECT(val, info.version, version);
+
+ info.wide_difficulty = difficulty_top64;
+ info.wide_difficulty <<= 64;
+ info.wide_difficulty += info.difficulty;
+
+ info.wide_cumulative_difficulty = cumulative_difficulty_top64;
+ info.wide_cumulative_difficulty <<= 64;
+ info.wide_cumulative_difficulty += info.cumulative_difficulty;
}
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist)
diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h
index 3868ab3f8..bbcde9bf6 100644
--- a/src/serialization/json_object.h
+++ b/src/serialization/json_object.h
@@ -281,7 +281,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResponse& response);
-void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, bool prune);
void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key);
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 2c51337ef..89691e9f7 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -2034,7 +2034,7 @@ bool simple_wallet::rpc_payment_info(const std::vector<std::string> &args)
crypto::public_key pkey;
crypto::secret_key_to_public_key(m_wallet->get_rpc_client_secret_key(), pkey);
message_writer() << tr("RPC client ID: ") << pkey;
- message_writer() << tr("RPC client secret key: ") << m_wallet->get_rpc_client_secret_key();
+ message_writer() << tr("RPC client secret key: ") << crypto::secret_key_explicit_print_ref{m_wallet->get_rpc_client_secret_key()};
if (!m_wallet->get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie))
{
fail_msg_writer() << tr("Failed to query daemon");
@@ -8186,9 +8186,9 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::secret_key> additional_tx_keys)
{
ostringstream oss;
- oss << epee::string_tools::pod_to_hex(tx_key);
+ oss << epee::string_tools::pod_to_hex(unwrap(unwrap(tx_key)));
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
- oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
+ oss << epee::string_tools::pod_to_hex(unwrap(unwrap(additional_tx_keys[i])));
return oss.str();
}
diff --git a/src/version.cpp.in b/src/version.cpp.in
index ac6ebaa89..857fa3588 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
-#define DEF_MONERO_VERSION "0.18.3.3"
+#define DEF_MONERO_VERSION "0.18.3.4"
#define DEF_MONERO_RELEASE_NAME "Fluorine Fermi"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index e9f76f4cf..8fda0bab7 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -921,7 +921,7 @@ std::string WalletImpl::integratedAddress(const std::string &payment_id) const
std::string WalletImpl::secretViewKey() const
{
- return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
+ return epee::string_tools::pod_to_hex(unwrap(unwrap(m_wallet->get_account().get_keys().m_view_secret_key)));
}
std::string WalletImpl::publicViewKey() const
@@ -931,7 +931,7 @@ std::string WalletImpl::publicViewKey() const
std::string WalletImpl::secretSpendKey() const
{
- return epee::string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key);
+ return epee::string_tools::pod_to_hex(unwrap(unwrap(m_wallet->get_account().get_keys().m_spend_secret_key)));
}
std::string WalletImpl::publicSpendKey() const
@@ -2043,9 +2043,9 @@ std::string WalletImpl::getTxKey(const std::string &txid_str) const
{
clearStatus();
std::ostringstream oss;
- oss << epee::string_tools::pod_to_hex(tx_key);
+ oss << epee::string_tools::pod_to_hex(unwrap(unwrap(tx_key)));
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
- oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
+ oss << epee::string_tools::pod_to_hex(unwrap(unwrap(additional_tx_keys[i])));
return oss.str();
}
else
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index e8991a326..dfb8b23cb 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1287,6 +1287,11 @@ bool wallet2::has_stagenet_option(const boost::program_options::variables_map& v
return command_line::get_arg(vm, options().stagenet);
}
+bool wallet2::has_proxy_option() const
+{
+ return !m_proxy.empty();
+}
+
std::string wallet2::device_name_option(const boost::program_options::variables_map& vm)
{
return command_line::get_arg(vm, options().hw_device);
@@ -1371,12 +1376,15 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
+bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options, const std::string& proxy)
{
boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
if(m_http_client->is_connected())
m_http_client->disconnect();
+ CHECK_AND_ASSERT_MES2(m_proxy.empty() || proxy.empty() , "It is not possible to set global proxy (--proxy) and daemon specific proxy together.");
+ if(m_proxy.empty())
+ CHECK_AND_ASSERT_MES(set_proxy(proxy), false, "failed to set proxy address");
const bool changed = m_daemon_address != daemon_address;
m_daemon_address = std::move(daemon_address);
m_daemon_login = std::move(daemon_login);
@@ -1411,7 +1419,8 @@ bool wallet2::set_proxy(const std::string &address)
//----------------------------------------------------------------------------------------------------
bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, const std::string &proxy_address, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
{
- CHECK_AND_ASSERT_MES(set_proxy(proxy_address), false, "failed to set proxy address");
+ m_proxy = proxy_address;
+ CHECK_AND_ASSERT_MES(set_proxy(m_proxy), false, "failed to set proxy address");
m_checkpoints.init_default_checkpoints(m_nettype);
m_is_initialized = true;
m_upper_transaction_weight_limit = upper_transaction_weight_limit;
@@ -3015,6 +3024,8 @@ void wallet2::get_short_chain_history(std::list<crypto::hash>& ids, uint64_t gra
size_t sz = blockchain_size - m_blockchain.offset();
if(!sz)
{
+ if(m_blockchain.size() > m_blockchain.offset())
+ ids.push_back(m_blockchain[m_blockchain.offset()]);
ids.push_back(m_blockchain.genesis());
return;
}
@@ -3687,6 +3698,7 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
req.requested_info = COMMAND_RPC_GET_BLOCKS_FAST::POOL_ONLY;
req.pool_info_since = m_pool_info_query_time;
+ req.prune = true;
{
const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
@@ -4749,7 +4761,7 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
original_address = get_account_address_as_str(m_nettype, false, m_original_address);
value.SetString(original_address.c_str(), original_address.length());
json.AddMember("original_address", value, json.GetAllocator());
- original_view_secret_key = epee::string_tools::pod_to_hex(m_original_view_secret_key);
+ original_view_secret_key = epee::string_tools::pod_to_hex(unwrap(unwrap(m_original_view_secret_key)));
value.SetString(original_view_secret_key.c_str(), original_view_secret_key.length());
json.AddMember("original_view_secret_key", value, json.GetAllocator());
}
@@ -7505,7 +7517,7 @@ void wallet2::commit_tx(pending_tx& ptx)
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq;
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::response ores;
oreq.address = get_account().get_public_address_str(m_nettype);
- oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ oreq.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
oreq.tx = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
{
const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
@@ -8435,7 +8447,7 @@ bool wallet2::sign_multisig_tx_from_file(const std::string &filename, std::vecto
return sign_multisig_tx_to_file(exported_txs, filename, txids);
}
//----------------------------------------------------------------------------------------------------
-uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask) const
+uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask)
{
if (use_per_byte_fee)
{
@@ -10531,7 +10543,7 @@ bool wallet2::light_wallet_login(bool &new_address)
tools::COMMAND_RPC_LOGIN::request request;
tools::COMMAND_RPC_LOGIN::response response;
request.address = get_account().get_public_address_str(m_nettype);
- request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ request.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
// Always create account if it doesn't exist.
request.create_account = true;
m_daemon_rpc_mutex.lock();
@@ -10558,7 +10570,7 @@ bool wallet2::light_wallet_import_wallet_request(tools::COMMAND_RPC_IMPORT_WALLE
MDEBUG("Light wallet import wallet request");
tools::COMMAND_RPC_IMPORT_WALLET_REQUEST::request oreq;
oreq.address = get_account().get_public_address_str(m_nettype);
- oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ oreq.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json("/import_wallet_request", oreq, response, rpc_timeout, "POST");
m_daemon_rpc_mutex.unlock();
@@ -10577,7 +10589,7 @@ void wallet2::light_wallet_get_unspent_outs()
oreq.amount = "0";
oreq.address = get_account().get_public_address_str(m_nettype);
- oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ oreq.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
// openMonero specific
oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD);
// below are required by openMonero api - but are not used.
@@ -10729,7 +10741,7 @@ bool wallet2::light_wallet_get_address_info(tools::COMMAND_RPC_GET_ADDRESS_INFO:
tools::COMMAND_RPC_GET_ADDRESS_INFO::request request;
request.address = get_account().get_public_address_str(m_nettype);
- request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ request.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json("/get_address_info", request, response, rpc_timeout, "POST");
m_daemon_rpc_mutex.unlock();
@@ -10746,7 +10758,7 @@ void wallet2::light_wallet_get_address_txs()
tools::COMMAND_RPC_GET_ADDRESS_TXS::response ires;
ireq.address = get_account().get_public_address_str(m_nettype);
- ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
+ ireq.view_key = string_tools::pod_to_hex(unwrap(unwrap(get_account().get_keys().m_view_secret_key)));
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json("/get_address_txs", ireq, ires, rpc_timeout, "POST");
m_daemon_rpc_mutex.unlock();
@@ -10976,7 +10988,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
const account_keys& ack = get_account().get_keys();
crypto::key_derivation derivation;
bool r = crypto::generate_key_derivation(tx_public_key, ack.m_view_secret_key, derivation);
- CHECK_AND_ASSERT_MES(r, false, "failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
+ CHECK_AND_ASSERT_MES(r, false, "failed to generate_key_derivation(" << tx_public_key << ", " << crypto::secret_key_explicit_print_ref{ack.m_view_secret_key} << ")");
r = crypto::derive_public_key(derivation, out_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub);
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key (" << derivation << ", " << out_index << ", " << ack.m_account_address.m_spend_public_key << ")");
@@ -10984,7 +10996,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
crypto::derive_secret_key(derivation, out_index, ack.m_spend_secret_key, in_ephemeral.sec);
crypto::public_key out_pkey_test;
r = crypto::secret_key_to_public_key(in_ephemeral.sec, out_pkey_test);
- CHECK_AND_ASSERT_MES(r, false, "failed to secret_key_to_public_key(" << in_ephemeral.sec << ")");
+ CHECK_AND_ASSERT_MES(r, false, "failed to secret_key_to_public_key(" << crypto::secret_key_explicit_print_ref{in_ephemeral.sec} << ")");
CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_pkey_test, false, "derived secret key doesn't match derived public key");
crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, calculated_key_image);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index d648cd5d3..2f4ad52f1 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1039,6 +1039,12 @@ private:
std::string path() const;
/*!
+ * \brief has_proxy_option Check the global proxy (--proxy) has been defined or not.
+ * \return returns bool representing the global proxy (--proxy).
+ */
+ bool has_proxy_option() const;
+
+ /*!
* \brief verifies given password is correct for default wallet keys file
*/
bool verify_password(const epee::wipeable_string& password) {crypto::secret_key key = crypto::null_skey; return verify_password(password, key);};
@@ -1069,7 +1075,8 @@ private:
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
bool set_daemon(std::string daemon_address = "http://localhost:8080",
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true,
- epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
+ epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect,
+ const std::string &proxy = "");
bool set_proxy(const std::string &address);
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
@@ -1651,7 +1658,7 @@ private:
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(const std::vector<std::pair<double, double>> &fee_levels);
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_tx_weight, uint64_t max_tx_weight, const std::vector<uint64_t> &fees);
- uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask) const;
+ static uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask);
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1);
uint64_t get_base_fee(uint32_t priority);
uint64_t get_base_fee();
@@ -1949,6 +1956,7 @@ private:
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
std::string m_daemon_address;
+ std::string m_proxy;
std::string m_wallet_file;
std::string m_keys_file;
std::string m_mms_file;
@@ -2568,7 +2576,7 @@ namespace boost
bool use_bulletproofs = x.rct_config.range_proof_type != rct::RangeProofBorromean;
a & use_bulletproofs;
if (!typename Archive::is_saving())
- x.rct_config = { use_bulletproofs ? rct::RangeProofBulletproof : rct::RangeProofBorromean, 0 };
+ x.rct_config = { use_bulletproofs ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean, 0 };
return;
}
a & x.rct_config;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index d24b4c563..14c66c5f5 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -1312,9 +1312,9 @@ namespace tools
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
{
- res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
+ res.tx_key_list.push_back(epee::string_tools::pod_to_hex(unwrap(unwrap(ptx.tx_key))));
for (const crypto::secret_key& additional_tx_key : ptx.additional_tx_keys)
- res.tx_key_list.back() += epee::string_tools::pod_to_hex(additional_tx_key);
+ res.tx_key_list.back() += epee::string_tools::pod_to_hex(unwrap(unwrap(additional_tx_key)));
}
}
@@ -3625,7 +3625,7 @@ namespace tools
if (!wal)
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to open wallet";
+ er.message = "Failed to open wallet : " + (!er.message.empty() ? er.message : "Unknown.");
return false;
}
@@ -4600,6 +4600,13 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
+
+ if (m_wallet->has_proxy_option() && !req.proxy.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_PROXY_ALREADY_DEFINED;
+ er.message = "It is not possible to set daemon specific proxy when --proxy is defined.";
+ return false;
+ }
std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints;
ssl_allowed_fingerprints.reserve(req.ssl_allowed_fingerprints.size());
@@ -4643,7 +4650,7 @@ namespace tools
if (!req.username.empty() || !req.password.empty())
daemon_login.emplace(req.username, req.password);
- if (!m_wallet->set_daemon(req.address, daemon_login, req.trusted, std::move(ssl_options)))
+ if (!m_wallet->set_daemon(req.address, daemon_login, req.trusted, std::move(ssl_options), req.proxy))
{
er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
er.message = std::string("Unable to set daemon");
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index a44b56ed6..72a35eb73 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -2598,6 +2598,7 @@ namespace wallet_rpc
std::string ssl_ca_file;
std::vector<std::string> ssl_allowed_fingerprints;
bool ssl_allow_any_cert;
+ std::string proxy;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
@@ -2610,6 +2611,7 @@ namespace wallet_rpc
KV_SERIALIZE(ssl_ca_file)
KV_SERIALIZE(ssl_allowed_fingerprints)
KV_SERIALIZE_OPT(ssl_allow_any_cert, false)
+ KV_SERIALIZE_OPT(proxy, (std::string)"")
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
diff --git a/tests/benchmark.cpp b/tests/benchmark.cpp
index 6a845d61a..660783dd9 100644
--- a/tests/benchmark.cpp
+++ b/tests/benchmark.cpp
@@ -109,7 +109,7 @@ namespace
template<typename T>
bool compare(const T& lhs, const T& rhs) noexcept
{
- static_assert(!epee::has_padding<T>(), "type might have padding");
+ static_assert(std::is_standard_layout<T>() && alignof(T) == 1, "type might have padding");
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(T)) == 0;
}
diff --git a/tests/core_tests/multisig.cpp b/tests/core_tests/multisig.cpp
index 966c76116..1d3a6a3a1 100644
--- a/tests/core_tests/multisig.cpp
+++ b/tests/core_tests/multisig.cpp
@@ -227,13 +227,13 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
CHECK_AND_ASSERT_MES(r, false, "Failed to generate multisig export key image");
}
MDEBUG("Party " << msidx << ":");
- MDEBUG("spend: sec " << miner_account[msidx].get_keys().m_spend_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_spend_public_key);
- MDEBUG("view: sec " << miner_account[msidx].get_keys().m_view_secret_key << ", pub " << miner_account[msidx].get_keys().m_account_address.m_view_public_key);
+ MDEBUG("spend: sec " << crypto::secret_key_explicit_print_ref{miner_account[msidx].get_keys().m_spend_secret_key} << ", pub " << miner_account[msidx].get_keys().m_account_address.m_spend_public_key);
+ MDEBUG("view: sec " << crypto::secret_key_explicit_print_ref{miner_account[msidx].get_keys().m_view_secret_key} << ", pub " << miner_account[msidx].get_keys().m_account_address.m_view_public_key);
for (const auto &k: miner_account[msidx].get_multisig_keys())
- MDEBUG("msk: " << k);
+ MDEBUG("msk: " << crypto::secret_key_explicit_print_ref{k});
for (size_t n = 0; n < account_k[msidx][tdidx].size(); ++n)
{
- MDEBUG("k: " << account_k[msidx][tdidx][n]);
+ MDEBUG("k: " << crypto::secret_key_explicit_print_ref{account_k[msidx][tdidx][n]});
MDEBUG("L: " << account_L[msidx][tdidx][n]);
MDEBUG("R: " << account_R[msidx][tdidx][n]);
}
@@ -406,7 +406,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
MDEBUG("signing with k " << k.back()[n]);
MDEBUG("signing with sk " << skey);
for (const auto &sk: used_keys)
- MDEBUG(" created with sk " << sk);
+ MDEBUG(" created with sk " << crypto::secret_key_explicit_print_ref{sk});
CHECK_AND_ASSERT_MES(signer_tx_builder.next_partial_sign(sig.total_alpha_G, sig.total_alpha_H, k, skey, sig.c_0, sig.s), false, "error: multisig::signing::tx_builder_ringct_t::next_partial_sign");
// in round-robin signing, the last signer finalizes the tx
diff --git a/tests/create_test_disks.sh b/tests/create_test_disks.sh
new file mode 100755
index 000000000..8e17c732d
--- /dev/null
+++ b/tests/create_test_disks.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+set -e
+
+LOOP_DEVICE_MAJOR=7
+LOOP_DEVICE_MIN_ID=100
+
+echo_err() {
+ echo "$@" >&2
+}
+
+root_exec() {
+ if [[ $EUID -ne 0 ]]; then
+ ${ROOT_EXEC_CMD:-sudo} "$@"
+ else
+ "$@"
+ fi
+}
+
+create_device_node() {
+ local -r last_id=$(find /dev/ -name 'loop[0-9]*' -printf '%f\n' | sed 's/^loop//' | sort -r -n | head -1)
+ local id=$((last_id + 1))
+ if [[ "$id" -lt "$LOOP_DEVICE_MIN_ID" ]]; then
+ id="$LOOP_DEVICE_MIN_ID"
+ fi
+ local path
+ for (( i=0; i<10; i++ )); do
+ path="/dev/loop$id"
+ if [[ ! -e "$path" ]] && root_exec mknod "$path" b "$LOOP_DEVICE_MAJOR" "$id"; then
+ echo "$path"
+ return 0
+ fi
+ $((id++))
+ done
+ return 1
+}
+
+device_mountpoint() {
+ local -r datadir="$1"
+ local -r dev="$2"
+ if [[ -z "$datadir" || -z "$dev" ]]; then
+ echo_err "Usage: device_mountpoint <data dir> <device>"
+ return 1
+ fi
+ echo "$datadir/mnt-$(basename "$dev")"
+}
+
+create_device() {
+ local -r datadir="$1"
+ if [[ -z "$datadir" ]]; then
+ echo_err "Usage: create_device <data dir>"
+ return 1
+ fi
+ local -r dev=$(create_device_node)
+ local -r fs="$datadir/$(basename "$dev").vhd"
+ local -r mountpoint=$(device_mountpoint "$datadir" "$dev")
+ echo_err
+ echo_err "# Device $dev"
+ dd if=/dev/zero of="$fs" bs=64K count=128 >/dev/null 2>&1
+ root_exec losetup "$dev" "$fs"
+ root_exec mkfs.ext4 "$dev" >/dev/null 2>&1
+ mkdir "$mountpoint"
+ root_exec mount "$dev" "$mountpoint"
+ echo "$dev"
+}
+
+# Unused by default, but helpful for local development
+destroy_device() {
+ local -r datadir="$1"
+ local -r dev="$2"
+ if [[ -z "$datadir" || -z "$dev" ]]; then
+ echo_err "Usage: destroy_device <data dir> <device>"
+ return 1
+ fi
+ echo_err "Destroying device $dev"
+ root_exec umount $(device_mountpoint "$datadir" "$dev")
+ root_exec losetup -d "$dev"
+ root_exec rm "$dev"
+}
+
+block_device_path() {
+ device_name=$(basename "$1")
+ device_minor=${device_name/#loop}
+ echo "/sys/dev/block/$LOOP_DEVICE_MAJOR:$device_minor"
+}
+
+tmpdir=$(mktemp --tmpdir -d monerotest.XXXXXXXX)
+echo_err "Creating devices using temporary directory: $tmpdir"
+
+dev_rot=$(create_device "$tmpdir")
+bdev_rot=$(block_device_path "$dev_rot")
+echo 1 | root_exec tee "$bdev_rot/queue/rotational" >/dev/null
+echo MONERO_TEST_DEVICE_HDD=$(device_mountpoint "$tmpdir" "$dev_rot")
+
+dev_ssd=$(create_device "$tmpdir")
+bdev_ssd=$(block_device_path "$dev_ssd")
+echo 0 | root_exec tee "$bdev_ssd/queue/rotational" >/dev/null
+echo MONERO_TEST_DEVICE_SSD=$(device_mountpoint "$tmpdir" "$dev_ssd")
diff --git a/tests/data/node/banlist_1.txt b/tests/data/node/banlist_1.txt
new file mode 100644
index 000000000..7cc94ca62
--- /dev/null
+++ b/tests/data/node/banlist_1.txt
@@ -0,0 +1,17 @@
+# magicfolk
+255.255.255.0 # Saruman the White
+128.128.128.0 # Gandalf the Gray
+150.75.0.0 # Radagast the Brown
+99.98.0.0/16 # All of Misty Mountain
+
+# personal enemies
+1.2.3.4 # this woman used to give me swirlies
+6.7.8.9 # I just don't like the cut of his jib
+1.0.0.7#Literally James Bond, he wrecked my aston martin
+100.98.1.13 # Earl from HOA
+100.98.1.0/24 #The rest of the HOA for good measure
+#
+
+#7.7.7.7
+#^^^We're chill now, she's truly an angel
+
diff --git a/tests/functional_tests/make_test_signature.cc b/tests/functional_tests/make_test_signature.cc
index e9dab8bd4..09a3f51c1 100644
--- a/tests/functional_tests/make_test_signature.cc
+++ b/tests/functional_tests/make_test_signature.cc
@@ -48,7 +48,7 @@ int main(int argc, const char **argv)
crypto::public_key pkey;
crypto::random32_unbiased((unsigned char*)skey.data);
crypto::secret_key_to_public_key(skey, pkey);
- printf("%s %s\n", epee::string_tools::pod_to_hex(skey).c_str(), epee::string_tools::pod_to_hex(pkey).c_str());
+ printf("%s %s\n", epee::string_tools::pod_to_hex(unwrap(unwrap(skey))).c_str(), epee::string_tools::pod_to_hex(pkey).c_str());
return 0;
}
diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp
index 7f926534a..329992463 100644
--- a/tests/unit_tests/crypto.cpp
+++ b/tests/unit_tests/crypto.cpp
@@ -72,10 +72,10 @@ TEST(Crypto, Ostream)
EXPECT_TRUE(is_formatted<crypto::hash8>());
EXPECT_TRUE(is_formatted<crypto::hash>());
EXPECT_TRUE(is_formatted<crypto::public_key>());
- EXPECT_TRUE(is_formatted<crypto::secret_key>());
EXPECT_TRUE(is_formatted<crypto::signature>());
EXPECT_TRUE(is_formatted<crypto::key_derivation>());
EXPECT_TRUE(is_formatted<crypto::key_image>());
+ EXPECT_TRUE(is_formatted<rct::key>());
}
TEST(Crypto, null_keys)
diff --git a/tests/unit_tests/dns_resolver.cpp b/tests/unit_tests/dns_resolver.cpp
index d56cbe45b..bc3691e59 100644
--- a/tests/unit_tests/dns_resolver.cpp
+++ b/tests/unit_tests/dns_resolver.cpp
@@ -41,15 +41,11 @@ TEST(DNSResolver, IPv4Success)
auto ips = resolver.get_ipv4("example.com", avail, valid);
- ASSERT_EQ(1, ips.size());
-
- //ASSERT_STREQ("93.184.216.119", ips[0].c_str());
+ ASSERT_LE(1, ips.size());
ips = tools::DNSResolver::instance().get_ipv4("example.com", avail, valid);
- ASSERT_EQ(1, ips.size());
-
- //ASSERT_STREQ("93.184.216.119", ips[0].c_str());
+ ASSERT_LE(1, ips.size());
}
TEST(DNSResolver, IPv4Failure)
@@ -76,9 +72,7 @@ TEST(DNSResolver, DNSSECSuccess)
auto ips = resolver.get_ipv4("example.com", avail, valid);
- ASSERT_EQ(1, ips.size());
-
- //ASSERT_STREQ("93.184.216.119", ips[0].c_str());
+ ASSERT_LE(1, ips.size());
ASSERT_TRUE(avail);
ASSERT_TRUE(valid);
diff --git a/tests/unit_tests/epee_serialization.cpp b/tests/unit_tests/epee_serialization.cpp
index f46630615..5e5b6e40f 100644
--- a/tests/unit_tests/epee_serialization.cpp
+++ b/tests/unit_tests/epee_serialization.cpp
@@ -29,8 +29,11 @@
#include <cstdint>
#include <gtest/gtest.h>
+#include <vector>
+#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage.h"
+#include "storages/portable_storage_template_helper.h"
#include "span.h"
TEST(epee_binary, two_keys)
@@ -54,3 +57,68 @@ TEST(epee_binary, duplicate_key)
epee::serialization::portable_storage storage{};
EXPECT_FALSE(storage.load_from_binary(data));
}
+
+namespace
+{
+
+template<typename t_param>
+struct ParentObjWithOptChild
+{
+ t_param params;
+
+ ParentObjWithOptChild(): params{} {}
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(params)
+ END_KV_SERIALIZE_MAP()
+};
+
+struct ObjWithOptChild
+{
+ bool test_value;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_OPT(test_value, true);
+ END_KV_SERIALIZE_MAP()
+};
+}
+
+TEST(epee_binary, serialize_deserialize)
+{
+ ParentObjWithOptChild<ObjWithOptChild> o;
+ std::string o_json;
+ o.params.test_value = true;
+
+ EXPECT_TRUE(epee::serialization::store_t_to_json(o, o_json));
+ EXPECT_TRUE(o.params.test_value);
+
+ EXPECT_TRUE(epee::serialization::load_t_from_json(o, o_json));
+ EXPECT_TRUE(o.params.test_value);
+
+ ParentObjWithOptChild<ObjWithOptChild> o2;
+ std::string o2_json;
+ o.params.test_value = false;
+
+ EXPECT_TRUE(epee::serialization::store_t_to_json(o2, o2_json));
+ EXPECT_FALSE(o2.params.test_value);
+
+ EXPECT_TRUE(epee::serialization::load_t_from_json(o2, o2_json));
+ EXPECT_FALSE(o2.params.test_value);
+
+ // compiler sets default value of test_value to false
+ ParentObjWithOptChild<ObjWithOptChild> o3;
+ std::string o3_json;
+
+ EXPECT_TRUE(epee::serialization::store_t_to_json(o3, o3_json));
+ EXPECT_FALSE(o3.params.test_value);
+
+ EXPECT_TRUE(epee::serialization::load_t_from_json(o3, o3_json));
+ EXPECT_FALSE(o3.params.test_value);
+
+ // test optional field default initialization.
+ ParentObjWithOptChild<ObjWithOptChild> o4;
+ std::string o4_json = "{\"params\": {}}";
+
+ EXPECT_TRUE(epee::serialization::load_t_from_json(o4, o4_json));
+ EXPECT_TRUE(o4.params.test_value);
+}
diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp
index d30bd3bd6..cc32f8bf3 100644
--- a/tests/unit_tests/epee_utils.cpp
+++ b/tests/unit_tests/epee_utils.cpp
@@ -1427,6 +1427,21 @@ TEST(StringTools, GetIpInt32)
EXPECT_EQ(htonl(0xff0aff00), ip);
}
+TEST(StringTools, GetExtension)
+{
+ EXPECT_EQ(std::string{}, epee::string_tools::get_extension(""));
+ EXPECT_EQ(std::string{}, epee::string_tools::get_extension("."));
+ EXPECT_EQ(std::string{"keys"}, epee::string_tools::get_extension("wallet.keys"));
+ EXPECT_EQ(std::string{"3"}, epee::string_tools::get_extension("1.2.3"));
+}
+
+TEST(StringTools, CutOffExtension)
+{
+ EXPECT_EQ(std::string{}, epee::string_tools::cut_off_extension(""));
+ EXPECT_EQ(std::string{"/home/user/Monero/wallets/wallet"}, epee::string_tools::cut_off_extension("/home/user/Monero/wallets/wallet"));
+ EXPECT_EQ(std::string{"/home/user/Monero/wallets/wallet"}, epee::string_tools::cut_off_extension("/home/user/Monero/wallets/wallet.keys"));
+}
+
TEST(NetUtils, IPv4NetworkAddress)
{
static_assert(epee::net_utils::ipv4_network_address::get_type_id() == epee::net_utils::address_type::ipv4, "bad ipv4 type id");
diff --git a/tests/unit_tests/is_hdd.cpp b/tests/unit_tests/is_hdd.cpp
index 040af4f47..55f759ed9 100644
--- a/tests/unit_tests/is_hdd.cpp
+++ b/tests/unit_tests/is_hdd.cpp
@@ -1,17 +1,36 @@
#include "common/util.h"
+#include <cstdlib>
#include <string>
#include <gtest/gtest.h>
+#include <boost/optional/optional_io.hpp> /* required to output boost::optional in assertions */
+
+#ifndef GTEST_SKIP
+#include <iostream>
+#define SKIP_TEST(reason) do {std::cerr << "Skipping test: " << reason << std::endl; return;} while(0)
+#else
+#define SKIP_TEST(reason) GTEST_SKIP() << reason
+#endif
#if defined(__GLIBC__)
-TEST(is_hdd, linux_os_root)
-{
- std::string path = "/";
- EXPECT_TRUE(tools::is_hdd(path.c_str()) != boost::none);
+TEST(is_hdd, rotational_drive) {
+ const char *hdd = std::getenv("MONERO_TEST_DEVICE_HDD");
+ if (hdd == nullptr)
+ SKIP_TEST("No rotational disk device configured");
+ EXPECT_EQ(tools::is_hdd(hdd), boost::optional<bool>(true));
}
-#else
-TEST(is_hdd, unknown_os)
-{
- std::string path = "";
- EXPECT_FALSE(tools::is_hdd(path.c_str()) != boost::none);
+
+TEST(is_hdd, ssd) {
+ const char *ssd = std::getenv("MONERO_TEST_DEVICE_SSD");
+ if (ssd == nullptr)
+ SKIP_TEST("No SSD device configured");
+ EXPECT_EQ(tools::is_hdd(ssd), boost::optional<bool>(false));
+}
+
+TEST(is_hdd, unknown_attrs) {
+ EXPECT_EQ(tools::is_hdd("/dev/null"), boost::none);
}
#endif
+TEST(is_hdd, stability)
+{
+ EXPECT_NO_THROW(tools::is_hdd(""));
+}
diff --git a/tests/unit_tests/json_serialization.cpp b/tests/unit_tests/json_serialization.cpp
index 9525d23ea..9ac019aec 100644
--- a/tests/unit_tests/json_serialization.cpp
+++ b/tests/unit_tests/json_serialization.cpp
@@ -124,6 +124,68 @@ TEST(JsonSerialization, InvalidVectorBytes)
EXPECT_THROW(cryptonote::json::fromJsonValue(doc, out), cryptonote::json::BAD_INPUT);
}
+TEST(JsonSerialization, DaemonInfo)
+{
+ cryptonote::rpc::DaemonInfo info{};
+ info.height = 154544;
+ info.target_height = 15345435;
+ info.top_block_height = 2344;
+ info.wide_difficulty = cryptonote::difficulty_type{"100000000000000000005443"};
+ info.difficulty = 200376420520695107;
+ info.target = 7657567;
+ info.tx_count = 355;
+ info.tx_pool_size = 45435;
+ info.alt_blocks_count = 43535;
+ info.outgoing_connections_count = 1444;
+ info.incoming_connections_count = 1444;
+ info.white_peerlist_size = 14550;
+ info.grey_peerlist_size = 34324;
+ info.mainnet = true;
+ info.testnet = true;
+ info.stagenet = true;
+ info.nettype = "main";
+ info.top_block_hash = crypto::hash{1};
+ info.wide_cumulative_difficulty = cryptonote::difficulty_type{"200000000000000000005543"};
+ info.cumulative_difficulty = 400752841041384871;
+ info.block_size_limit = 4324234;
+ info.block_weight_limit = 3434;
+ info.block_size_median = 3434;
+ info.adjusted_time = 4535;
+ info.block_weight_median = 43535;
+ info.start_time = 34535;
+ info.version = "1.0";
+
+ const auto info_copy = test_json(info);
+
+ EXPECT_EQ(info.height, info_copy.height);
+ EXPECT_EQ(info.target_height, info_copy.target_height);
+ EXPECT_EQ(info.top_block_height, info_copy.top_block_height);
+ EXPECT_EQ(info.wide_difficulty, info_copy.wide_difficulty);
+ EXPECT_EQ(info.difficulty, info_copy.difficulty);
+ EXPECT_EQ(info.target, info_copy.target);
+ EXPECT_EQ(info.tx_count, info_copy.tx_count);
+ EXPECT_EQ(info.tx_pool_size, info_copy.tx_pool_size);
+ EXPECT_EQ(info.alt_blocks_count, info_copy.alt_blocks_count);
+ EXPECT_EQ(info.outgoing_connections_count, info_copy.outgoing_connections_count);
+ EXPECT_EQ(info.incoming_connections_count, info_copy.incoming_connections_count);
+ EXPECT_EQ(info.white_peerlist_size, info_copy.white_peerlist_size);
+ EXPECT_EQ(info.grey_peerlist_size, info_copy.grey_peerlist_size);
+ EXPECT_EQ(info.mainnet, info_copy.mainnet);
+ EXPECT_EQ(info.testnet, info_copy.testnet);
+ EXPECT_EQ(info.stagenet, info_copy.stagenet);
+ EXPECT_EQ(info.nettype, info_copy.nettype);
+ EXPECT_EQ(info.top_block_hash, info_copy.top_block_hash);
+ EXPECT_EQ(info.wide_cumulative_difficulty, info_copy.wide_cumulative_difficulty);
+ EXPECT_EQ(info.cumulative_difficulty, info_copy.cumulative_difficulty);
+ EXPECT_EQ(info.block_size_limit, info_copy.block_size_limit);
+ EXPECT_EQ(info.block_weight_limit, info_copy.block_weight_limit);
+ EXPECT_EQ(info.block_size_median, info_copy.block_size_median);
+ EXPECT_EQ(info.adjusted_time, info_copy.adjusted_time);
+ EXPECT_EQ(info.block_weight_median, info_copy.block_weight_median);
+ EXPECT_EQ(info.start_time, info_copy.start_time);
+ EXPECT_EQ(info.version, info_copy.version);
+}
+
TEST(JsonSerialization, MinerTransaction)
{
cryptonote::account_base acct;
diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp
index 103bac08f..6eac92de7 100644
--- a/tests/unit_tests/levin.cpp
+++ b/tests/unit_tests/levin.cpp
@@ -2219,6 +2219,63 @@ TEST_F(levin_notify, fluff_multiple)
}
}
+TEST_F(levin_notify, fluff_with_duplicate)
+{
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
+
+ for (unsigned count = 0; count < 10; ++count)
+ add_connection(count % 2 == 0);
+
+ {
+ const auto status = notifier.get_status();
+ EXPECT_FALSE(status.has_noise);
+ EXPECT_FALSE(status.connections_filled);
+ EXPECT_TRUE(status.has_outgoing);
+ }
+ notifier.new_out_connection();
+ io_service_.poll();
+
+ std::vector<cryptonote::blobdata> txs(9);
+ txs[0].resize(100, 'e');
+ txs[1].resize(100, 'e');
+ txs[2].resize(100, 'e');
+ txs[3].resize(100, 'e');
+ txs[4].resize(200, 'f');
+ txs[5].resize(200, 'f');
+ txs[6].resize(200, 'f');
+ txs[7].resize(200, 'f');
+ txs[8].resize(200, 'f');
+
+ ASSERT_EQ(10u, contexts_.size());
+ {
+ auto context = contexts_.begin();
+ EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), cryptonote::relay_method::fluff));
+
+ io_service_.reset();
+ ASSERT_LT(0u, io_service_.poll());
+ notifier.run_fluff();
+ ASSERT_LT(0u, io_service_.poll());
+
+ EXPECT_EQ(0u, context->process_send_queue());
+ for (++context; context != contexts_.end(); ++context)
+ EXPECT_EQ(1u, context->process_send_queue());
+
+ EXPECT_EQ(txs, events_.take_relayed(cryptonote::relay_method::fluff));
+ std::sort(txs.begin(), txs.end());
+ ASSERT_EQ(9u, receiver_.notified_size());
+ for (unsigned count = 0; count < 9; ++count)
+ {
+ auto notification = receiver_.get_notification<cryptonote::NOTIFY_NEW_TRANSACTIONS>().second;
+ EXPECT_NE(txs, notification.txs);
+ EXPECT_EQ(notification.txs.size(), 2);
+ EXPECT_TRUE(notification._.empty());
+ EXPECT_TRUE(notification.dandelionpp_fluff);
+ }
+ }
+
+}
+
TEST_F(levin_notify, noise)
{
for (unsigned count = 0; count < 10; ++count)
diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp
index 3b3c4197c..71416aaf3 100644
--- a/tests/unit_tests/multisig.cpp
+++ b/tests/unit_tests/multisig.cpp
@@ -80,7 +80,7 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet)
wallet.generate("", "", spendkey, true, false);
ASSERT_TRUE(test_addresses[idx].address == wallet.get_account().get_public_address_str(cryptonote::TESTNET));
wallet.decrypt_keys("");
- ASSERT_TRUE(test_addresses[idx].spendkey == epee::string_tools::pod_to_hex(wallet.get_account().get_keys().m_spend_secret_key));
+ ASSERT_TRUE(test_addresses[idx].spendkey == epee::string_tools::pod_to_hex(unwrap(unwrap(wallet.get_account().get_keys().m_spend_secret_key))));
wallet.encrypt_keys("");
}
catch (const std::exception &e)
diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp
index 584f98f7a..09b1d5461 100644
--- a/tests/unit_tests/node_server.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -35,6 +35,7 @@
#include "cryptonote_core/i_core_events.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.inl"
+#include "unit_tests_utils.h"
#include <condition_variable>
#define MAKE_IPV4_ADDRESS(a,b,c,d) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),0}
@@ -114,6 +115,18 @@ static bool is_blocked(Server &server, const epee::net_utils::network_address &a
return true;
}
}
+
+ if (address.get_type_id() != epee::net_utils::address_type::ipv4)
+ return false;
+
+ const epee::net_utils::ipv4_network_address ipv4_address = address.as<epee::net_utils::ipv4_network_address>();
+
+ // check if in a blocked ipv4 subnet
+ const std::map<epee::net_utils::ipv4_network_subnet, time_t> subnets = server.get_blocked_subnets();
+ for (const auto &subnet : subnets)
+ if (subnet.first.matches(ipv4_address))
+ return true;
+
return false;
}
@@ -224,6 +237,18 @@ TEST(ban, subnet)
test_core pr_core;
cryptonote::t_cryptonote_protocol_handler<test_core> cprotocol(pr_core, NULL);
Server server(cprotocol);
+ {
+ boost::program_options::options_description opts{};
+ Server::init_options(opts);
+ cryptonote::core::init_options(opts);
+
+ char** args = nullptr;
+ boost::program_options::variables_map vm;
+ boost::program_options::store(
+ boost::program_options::parse_command_line(0, args, opts), vm
+ );
+ server.init(vm);
+ }
cprotocol.set_p2p_endpoint(&server);
ASSERT_TRUE(server.block_subnet(MAKE_IPV4_SUBNET(1,2,3,4,24), 10));
@@ -266,6 +291,78 @@ TEST(ban, ignores_port)
ASSERT_FALSE(is_blocked(server,MAKE_IPV4_ADDRESS_PORT(1,2,3,4,6)));
}
+TEST(ban, file_banlist)
+{
+ test_core pr_core;
+ cryptonote::t_cryptonote_protocol_handler<test_core> cprotocol(pr_core, NULL);
+ Server server(cprotocol);
+ cprotocol.set_p2p_endpoint(&server);
+
+ auto create_node_dir = [](){
+ boost::system::error_code ec;
+ auto path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("daemon-%%%%%%%%%%%%%%%%", ec);
+ if (ec)
+ return boost::filesystem::path{};
+ auto success = boost::filesystem::create_directory(path, ec);
+ if (!ec && success)
+ return path;
+ return boost::filesystem::path{};
+ };
+ const auto node_dir = create_node_dir();
+ ASSERT_TRUE(!node_dir.empty());
+ auto auto_remove_node_dir = epee::misc_utils::create_scope_leave_handler([&node_dir](){
+ boost::filesystem::remove_all(node_dir);
+ });
+
+ boost::program_options::variables_map vm;
+ boost::program_options::store(
+ boost::program_options::command_line_parser({
+ "--data-dir",
+ node_dir.string(),
+ "--ban-list",
+ (unit_test::data_dir / "node" / "banlist_1.txt").string()
+ }).options([]{
+ boost::program_options::options_description options_description{};
+ cryptonote::core::init_options(options_description);
+ Server::init_options(options_description);
+ return options_description;
+ }()).run(),
+ vm
+ );
+
+ ASSERT_TRUE(server.init(vm));
+
+ // Test cases (look in the banlist_1.txt file)
+
+ // magicfolk
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(255,255,255,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(128,128,128,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(150,75,0,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,255,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,255,255,9999)) );
+ EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,99,0,0,9999)) );
+
+ // personal enemies
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,2,3,4,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(6,7,8,9,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,13,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,0,9999)) );
+ EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,255,9999)) );
+ EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,2,0,9999)) );
+ EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,0,255,9999)) );
+
+ // angel
+ EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(007,007,007,007,9999)) );
+
+ // random IP
+ EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(145,036,205,235,9999)) );
+}
+
TEST(node_server, bind_same_p2p_port)
{
struct test_data_t
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 0fdd83285..fdf603272 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -1103,7 +1103,7 @@ TEST(Serialization, portability_signed_tx)
ASSERT_TRUE(ptx.selected_transfers.front() == 2);
// ptx.{key_images, tx_key}
ASSERT_TRUE(ptx.key_images == "<6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76> ");
- ASSERT_TRUE(epee::string_tools::pod_to_hex(ptx.tx_key) == "0100000000000000000000000000000000000000000000000000000000000000");
+ ASSERT_TRUE(epee::string_tools::pod_to_hex(unwrap(unwrap(ptx.tx_key))) == "0100000000000000000000000000000000000000000000000000000000000000");
// ptx.dests
ASSERT_TRUE(ptx.dests.size() == 1);
ASSERT_TRUE(ptx.dests[0].amount == 1400000000000);
diff --git a/utils/fish/monerod.fish b/utils/fish/monerod.fish
index d2836a6b2..04003f0ff 100644
--- a/utils/fish/monerod.fish
+++ b/utils/fish/monerod.fish
@@ -79,8 +79,8 @@ complete -c monerod -l igd -r -a "Enabled disabled enabled" -d "UPnP port mappin
complete -c monerod -l out-peers -r -d "Set max number of out peers. Default: -1"
complete -c monerod -l in-peers -r -d "Set max number of in peers. Default: -1"
complete -c monerod -l tos-flag -r -d "Set TOS flag. Default: -1"
-complete -c monerod -l limit-rate-up -r -d "Set limit-rate-up [kB/s]. Default: 2048"
-complete -c monerod -l limit-rate-down -r -d "Set limit-rate-down [kB/s]. Default: 8192"
+complete -c monerod -l limit-rate-up -r -d "Set limit-rate-up [kB/s]. Default: 8192"
+complete -c monerod -l limit-rate-down -r -d "Set limit-rate-down [kB/s]. Default: 32768"
complete -c monerod -l limit-rate -r -d "Set limit-rate [kB/s]. Default: -1"
complete -c monerod -l pad-transactions -d "Pad relayed transactions to help defend against traffic volume analysis"
complete -c monerod -l max-connections-per-ip -r -d "Maximum number of connections allowed from the same IP address. Default: 1"
diff --git a/utils/systemd/monerod.service b/utils/systemd/monerod.service
index 63daefa82..28b457d56 100644
--- a/utils/systemd/monerod.service
+++ b/utils/systemd/monerod.service
@@ -1,6 +1,6 @@
[Unit]
Description=Monero Full Node
-After=network.target
+After=network-online.target
[Service]
User=monero