Compare commits

..

107 Commits

Author SHA1 Message Date
wowario
3e302be710 Merge pull request 'upstream' (#494) from wowario/wownero:upstream into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/494
2024-12-15 21:38:34 +00:00
nsec1
b4ea97713d fix zmq and sodium include dirs search 2024-12-15 23:51:09 +03:00
tobtoht
3e5fbb4fec wallet2: fix error throw if unable to load cache 2024-12-15 23:49:04 +03:00
Lee Clagett
178f454742 Relax static_asserts in src/lmdb 2024-12-15 23:47:57 +03:00
Lee *!* Clagett
345be3361e Add byte_stream value_type and data() 2024-12-15 23:46:16 +03:00
Lee *!* Clagett
5ad6661274 Fix memcpy in byte_slice constructor 2024-12-15 23:40:56 +03:00
0xFFFC0000
cd1de16fc2 Daemon-specific proxy for the wallet-rpc.
1. Daemon-specific proxy is exclusive with global proxy (--proxy).
2. If you set global proxy (--proxy) you cannot set daemon-specific proxy.
3. If you don't set global proxy, you can set proxy (or not set) proxy for
each daemon connection with the proxy field in jsonrpc to the wallet-rpc.
2024-12-15 23:39:48 +03:00
0xFFFC0000
c9d4dd1082 simplewallet: add header to show_transfers command 2024-12-15 23:37:37 +03:00
wowario
7d44e42dde Merge pull request 'Decoy selection fix' (#489) from wowario/wownero:decoy-fix into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/489
2024-12-15 20:30:27 +00:00
jeffro256
6481a9ba5e Blockchain: fix temp fails causing alt blocks to be permanently invalid 2024-12-15 19:55:18 +03:00
jeffro256
e5dc1f749f epee: partially revert c56ee140 to fix linking errors
On Linux Mint 21.3, g++ Ubuntu 11.4.0-1ubuntu1~22.04, I get linking error for an undefined reference to `epee::string_tools::trim_right`. This PR reverts the changes
to epee_readline.cpp in commit c56ee140, which turns a `boost::trim_right` callsite into an `epee::string_tools::trim_right` callsite.
2024-12-15 19:52:38 +03:00
0xFFFC0000
7d01e5fa30 wallet: report exact reason for open_wallet failure. 2024-12-15 19:51:50 +03:00
0xFFFC0000
f603c70a5f contrib: force (de)serialization to create params section incase there is none.
Co-authored-by: Boog900 <boog900@tutanota.com>
2024-12-15 19:51:27 +03:00
jeffro256
d807ab95f1 p2p: allow comments in banlist files
In-line comments explicitly explaining banned hosts/subnets might help assuage fears of some good banlists' arbitaryiness.
2024-12-15 19:50:53 +03:00
wowario
b79968a7d8 Merge pull request 'add gcc13 dependency' (#493) from wowario/wownero:gcc into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/493
2024-12-15 16:14:47 +00:00
wowario
c7fc4993cb add gcc13 dependency 2024-12-15 19:11:34 +03:00
wowario
4b4882082e Merge pull request 'Update checkpoints and bump version' (#492) from wowario/wownero:checkpoints into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/492
2024-12-15 13:20:19 +00:00
wowario
2f7d418bda bump version 2024-12-15 10:50:17 +03:00
wowario
2d01af02ef update checkpoints 2024-12-15 10:49:25 +03:00
wowario
1ff387c933 cmake: boost: fix header-only library search, bump minimum (#491)
Co-authored-by: tobtoht <tob@featherwallet.org>
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/491
2024-12-15 07:25:29 +00:00
wowario
054abe1fa4 Merge pull request 'Revert Miniupnpc commits for gitian builds' (#490) from wowario/wownero:revert into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/490
2024-12-15 07:24:16 +00:00
wowario
d6e7550793 Revert "cmake: add different parameters to add_monero_library."
This reverts commit 4bbad537aa.
2024-12-15 10:00:02 +03:00
wowario
194b88bf4f Revert "cmake: remove extera cmake/FindMiniupnpc.cmake and only rely on external/miniupnpc."
This reverts commit 31f5bc908d.
2024-12-15 09:59:35 +03:00
wowario
50c24fb1bb Revert "external: update miniupnpc to 2.2.8"
This reverts commit 5fe3cf2349.
2024-12-15 09:58:58 +03:00
wowario
60386e7cf4 RingCT start height 2024-12-14 09:56:43 +03:00
wowario
ff0fb4b6ed revert revert sanity check 2024-12-14 09:53:01 +03:00
wowario
dd46a31f3c Merge pull request 'update gitian urls' (#486) from wowario/wownero:pr into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/486
2024-09-26 13:03:46 +00:00
wowario
9e4ae1a36a update gitian urls 2024-09-26 15:59:14 +03:00
wowario
36a6641000 Merge pull request 'Rebase to Monero v0.18.3.4' (#485) from wowario/wownero:pr into master
Reviewed-on: https://codeberg.org/wownero/wownero/pulls/485
2024-09-25 18:39:38 +00:00
wowario
9a8bbc6091 v0.11 ASCII art
Signed-off-by: wowario <wowario@protonmail.com>
2024-09-25 12:07:39 +03:00
wowario
916f84b57b update randomwow 2024-09-25 12:07:38 +03:00
wowario
18399b17a1 add README.md 2024-09-25 12:07:38 +03:00
wowario
7f984b6734 remove README.md 2024-09-25 12:07:38 +03:00
wowario
c826b2f098 update checkpoints.dat 2024-09-25 12:07:38 +03:00
wowario
a3a0dceb6c update public nodes 2024-09-25 12:07:37 +03:00
0xFFFC0000
4796f9fa18 simplewallet: change boost::filesystem::complete to absolute. 2024-09-25 12:07:37 +03:00
jeffro256
fb65602fbb build: fix build with Boost 1.85 and remove instances of viewkey logging [RELEASE]
1. Use std::is_standard_layout and std::is_trivially_copyable instead of std::is_pod for KV byte-wise serialization, which fixes compile issue for Boost UUIDs
2. Removed reimplementation of std::hash for boost::uuids::uuid
3. Removed << operator overload for crypto::secret_key
4. Removed instances in code where private view key was dumped to the log in plaintext

Release version of #9450, containing C++14 modified assertions
2024-09-25 12:07:37 +03:00
0xFFFC0000
5fe3cf2349 external: update miniupnpc to 2.2.8 2024-09-25 12:07:37 +03:00
0xFFFC0000
4bbad537aa cmake: add different parameters to add_monero_library.
1. LINKS flag, will link publicly the libraries provided.
2. PRIVATE_LINKS flag, will link privately the libraries provided.
3. INCLUDES flag, will includes publicly the dirs provided.
4. PRIVATE_INCLUDES flag, will include privately the libraries provided.
2024-09-25 12:07:37 +03:00
0xFFFC0000
31f5bc908d cmake: remove extera cmake/FindMiniupnpc.cmake and only rely on external/miniupnpc. 2024-09-25 12:07:36 +03:00
wowario
33a9bfed1f disable mismatched daemon check 2024-09-25 12:07:36 +03:00
wowario
6728edc0e5 remove nudge in daemon_is_outdated 2024-09-25 12:07:36 +03:00
wowario
669d13edae remove nudge in num_mainnet_hard_forks 2024-09-25 12:07:36 +03:00
_XxFedexX_
42db984de2 Add _xxfedexx_'s PGP key 2024-09-25 12:07:35 +03:00
wowario
fe5350d36a remove rx_set code 2024-09-25 12:07:35 +03:00
wowario
1d85179c40 use rx_set_miner_thread after RX_BLOCK_VERSION 2024-09-25 12:07:35 +03:00
moneromooo-monero
7d6b6eee1b simplewallet: print fully qualified filename for new wallets
from time to time, some people don't realize their wallets get
created in their current working directory
2024-09-25 12:07:35 +03:00
wowario
e8a9afe632 add wowario PGP key 2024-09-25 12:07:35 +03:00
w0wΔri0
b5eb15d75b Revoke old pgp key 2024-09-25 12:07:34 +03:00
wowario
cbe4d95a5b support old ass BPs 2024-09-25 12:07:34 +03:00
wowario
611809cd62 revert sanity check 2024-09-25 12:07:34 +03:00
wowario
5336b464df wallet seed message spacing 2024-09-25 12:07:34 +03:00
wowario
5b74f3a8f7 remove warning reusing keys 2024-09-25 12:07:34 +03:00
wowario
53fdd5641a remove warning about background mining 2024-09-25 12:07:33 +03:00
wowario
37d6a815ff add clear screen command 2024-09-25 12:07:33 +03:00
wowario
6c3f6122cf wownero chan 2024-09-25 12:07:33 +03:00
wowario
a2ba4811d5 set fork height 2024-09-25 12:07:33 +03:00
wowario
75ea6cdc79 from v20, limit tx extra size 2024-09-25 12:07:33 +03:00
wowario
0882e5085e Debug level No incoming connections 2024-09-25 12:07:32 +03:00
wowario
a4b7df3bd3 uri remainder 2024-09-25 12:07:32 +03:00
wowario
f4a93f581c remove testnet/stagenet fork heights/blocks 2024-09-25 12:07:32 +03:00
wowario
75bd0fa857 don't request pre-bulletprooof pruned blocks 2024-09-25 12:07:32 +03:00
wowario
2a0ac54f75 change to debug level 2024-09-25 12:07:31 +03:00
wowario
bede30caf2 rename ringdb-dir 2024-09-25 12:07:31 +03:00
wowario
0d7434b17c mod variant4_random_math 2024-09-25 12:07:31 +03:00
wowario
93e10f8017 support old BP 2024-09-25 12:07:31 +03:00
wowario
e3df46c1d7 vote by block 2024-09-25 12:07:31 +03:00
wowario
dc2f340641 tidy up miner msgs 2024-09-25 12:07:30 +03:00
wowario
45c1adb578 miner block header signing 2024-09-25 12:07:30 +03:00
wowario
eb9944a57d difficulty is fun 2024-09-25 12:07:30 +03:00
wowario
4eed6ac172 shorten timestamp check window 2024-09-25 12:07:30 +03:00
wowario
25d070429e limit future blk time to 10 min 2024-09-25 12:07:30 +03:00
wowario
8ae0fb546c bump unlock time to 288 blks 2024-09-25 12:07:29 +03:00
wowario
ca6a01cf55 broadcast donation sub-address 2024-09-25 12:07:29 +03:00
wowario
b90d2892da revert Preserve commitment format inside transactions #8277 2024-09-25 12:07:29 +03:00
wowario
8d8781e35e add systemd file 2024-09-25 12:07:29 +03:00
wowario
60df4f6e92 update gitian 2024-09-25 12:07:29 +03:00
wowario
46e657b0af update Dockerfile 2024-09-25 12:07:28 +03:00
wowario
cbeabcaed0 adjust approx_blockchain_height 2024-09-25 12:07:28 +03:00
wowario
29cf2b690f add wowario gpg key 2024-09-25 12:07:28 +03:00
wowario
2585070fd6 config wallet2 settings 2024-09-25 12:07:28 +03:00
wowario
dfb9ddbca5 set dev fund address 2024-09-25 12:07:28 +03:00
wowario
9aa0587063 add seed nodes 2024-09-25 12:07:27 +03:00
wowario
6d47fb1b86 set name of daemon stdout 2024-09-25 12:07:27 +03:00
wowario
ffd31aacfb set last v1 block 2024-09-25 12:07:27 +03:00
wowario
ddf62fb149 set pow variants 2024-09-25 12:07:27 +03:00
wowario
81d424efb0 set quick height for syncing 2024-09-25 12:07:27 +03:00
wowario
9c306cf2cf send dump log to wowario 2024-09-25 12:07:26 +03:00
wowario
00e7562e5f set genesis block timestamp 2024-09-25 12:07:26 +03:00
wowario
a883a1c438 set decimal point 2024-09-25 12:07:26 +03:00
wowario
66eb48c94e add forks and checkpoints 2024-09-25 12:07:26 +03:00
wowario
645111f755 wownero skin pack 2024-09-25 12:07:25 +03:00
wowario
d69c44d7a7 bump RX block version 2024-09-25 12:07:25 +03:00
wowario
d82736ad96 correct length of addresses 2024-09-25 12:07:25 +03:00
wowario
d7b5232a37 move utilities to debug build 2024-09-25 12:07:25 +03:00
wowario
ce4214f9dc automatic submodule update 2024-09-25 12:07:25 +03:00
wowario
126822f955 Doxygen off 2024-09-25 12:07:25 +03:00
wowario
b34c76d44c trezor support off 2024-09-25 12:07:24 +03:00
wowario
e37fa68509 turn off tests 2024-09-25 12:07:24 +03:00
wowario
69d8548576 gitian: copy config file 2024-09-25 12:07:24 +03:00
wowario
b8c99d6b09 add RandomWOW 2024-09-25 12:07:24 +03:00
wowario
7b97b5a96e show full version 2024-09-25 12:07:24 +03:00
wowario
0abb30480f remove moneropulse urls 2024-09-25 12:07:23 +03:00
wowario
8708560330 remove monero tx bug fixes 2024-09-25 12:07:23 +03:00
wowario
0d147fa64c bump ring size to 22 2024-09-25 12:07:23 +03:00
wowario
a0b96b5609 initialize genesis block 2024-09-25 12:07:23 +03:00
wowario
3cdf08cf48 config cryptonote 2024-09-25 12:07:18 +03:00
200 changed files with 4691 additions and 7186 deletions

View File

@@ -1,327 +0,0 @@
name: Build Wownero Core (Libevent FailSafe)
on:
push:
branches: [ master, main ]
tags: [ 'v*' ]
workflow_dispatch:
env:
NODE_TLS_REJECT_UNAUTHORIZED: '0'
jobs:
build-all:
runs-on: ubuntu-latest
container:
image: wownero-builder-base:latest
strategy:
fail-fast: false
matrix:
target:
- x86_64-linux-gnu # Linux x64
- x86_64-w64-mingw32 # Windows x64
- aarch64-linux-gnu # Linux ARM64
- riscv64-linux-gnu # Linux RISC-V
- x86_64-apple-darwin11 # macOS Intel
- aarch64-apple-darwin11 # macOS ARM
steps:
- name: Fix DNS
run: echo "192.168.88.230 git.such.software" >> /etc/hosts
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
token: ${{ secrets.GITHUB_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Configure Git URLs
run: |
git config --global --add safe.directory '*'
git config --global url."http://oauth2:${GITHUB_TOKEN}@git.such.software:3000/Builds/RandomWOW.git".insteadOf "https://codeberg.org/wownero/RandomWOW"
git config --global url."http://oauth2:${GITHUB_TOKEN}@git.such.software:3000/Builds/wownero.git".insteadOf "https://codeberg.org/wownero/wownero.git"
- name: Download macOS SDK
if: contains(matrix.target, 'apple')
run: |
mkdir -p contrib/depends/SDKs
curl -L -k -o contrib/depends/SDKs/MacOSX10.15.sdk.tar.gz \
"https://github.com/phracker/MacOSX-SDKs/releases/download/10.15/MacOSX10.15.sdk.tar.gz"
- name: Install Modern CMake
run: |
curl -L -o cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.28.1/cmake-3.28.1-linux-x86_64.tar.gz
tar -xf cmake.tar.gz
echo "$(pwd)/cmake-3.28.1-linux-x86_64/bin" >> $GITHUB_PATH
# -----------------------------------------------------------------------
# 1. BUILD CONFIGURATION
# -----------------------------------------------------------------------
- name: Sanitize Makefiles (Stable + Mac Compat)
run: |
curl -L -o contrib/depends/funcs.mk https://codeberg.org/wownero/wownero/raw/branch/master/contrib/depends/funcs.mk
curl -L -o contrib/depends/packages/packages.mk https://codeberg.org/wownero/wownero/raw/branch/master/contrib/depends/packages/packages.mk
# Inject packages: libevent added before unbound
sed -i 's/^packages :=.*/packages := boost openssl expat libusb hidapi protobuf libiconv sodium zeromq libevent unbound zlib zstd/' contrib/depends/packages/packages.mk
# GENERATE LIBEVENT.MK (Attempt 1: Makefiles)
cat <<'EOF' > contrib/depends/packages/libevent.mk
package=libevent
$(package)_version=2.1.12-stable
$(package)_download_path=https://github.com/libevent/libevent/releases/download/release-$($(package)_version)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=92e6de1be9ec176428fd2367677e61ecedc2fc1cb11bc61069461ea910c1d4d7
define $(package)_set_vars
$(package)_config_opts=--disable-shared --disable-openssl --disable-libenc --disable-samples --disable-debug-mode --prefix=$($(package)_staging_prefix_dir)
endef
define $(package)_config_cmds
./configure $($(package)_config_opts) --host=${host}
endef
define $(package)_build_cmds
$(MAKE)
endef
define $(package)_stage_cmds
$(MAKE) install
endef
EOF
sed -i 's/^ /\t/' contrib/depends/packages/libevent.mk
# GENERATE ZLIB.MK
cat <<'EOF' > contrib/depends/packages/zlib.mk
package=zlib
$(package)_version=1.3.1
$(package)_download_path=https://zlib.net/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
define $(package)_set_vars
$(package)_config_opts=--static
endef
define $(package)_config_cmds
CHOST=${host} ./configure $($(package)_config_opts) --prefix=$($(package)_staging_prefix_dir)
endef
define $(package)_build_cmds
$(MAKE) libz.a
endef
define $(package)_stage_cmds
$(MAKE) install
endef
EOF
sed -i 's/^ /\t/' contrib/depends/packages/zlib.mk
# GENERATE ZSTD.MK
cat <<'EOF' > contrib/depends/packages/zstd.mk
package=zstd
$(package)_version=1.5.5
$(package)_download_path=https://github.com/facebook/zstd/releases/download/v$($(package)_version)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4
define $(package)_build_cmds
$(MAKE) -C lib libzstd.a
endef
define $(package)_stage_cmds
cp lib/libzstd.a $($(package)_staging_prefix_dir)/lib/
cp lib/zstd.h $($(package)_staging_prefix_dir)/include/
endef
EOF
sed -i 's/^ /\t/' contrib/depends/packages/zstd.mk
# GENERATE BOOST.MK
cat <<'EOF' > contrib/depends/packages/boost.mk
package=boost
$(package)_version=1.90.0
$(package)_download_path=https://archives.boost.io/release/$($(package)_version)/source/
$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.bz2
$(package)_sha256_hash=49551aff3b22cbc5c5a9ed3dbc92f0e23ea50a0f7325b0d198b705e8ee3fc305
$(package)_dependencies=libiconv
define $(package)_set_vars
$(package)_config_opts_release=variant=release
$(package)_config_opts_debug=variant=debug
$(package)_config_opts+=--layout=system --user-config=user-config.jam
$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
$(package)_config_opts_linux=threadapi=pthread runtime-link=static
$(package)_config_opts_darwin=target-os=darwin runtime-link=shared
$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
$(package)_config_opts_x86_64_mingw32=address-model=64
$(package)_config_opts_i686_mingw32=address-model=32
$(package)_config_opts_i686_linux=address-model=32 architecture=x86
$(package)_config_opts_x86_64_darwin=address-model=64
$(package)_config_opts_aarch64_darwin=address-model=64 architecture=arm binary-format=mach-o abi=aapcs
$(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=darwin
$(package)_archiver_darwin=$($(package)_libtool)
$(package)_config_libraries=atomic,chrono,date_time,filesystem,program_options,regex,serialization,system,thread,locale,context,coroutine
$(package)_cxxflags=-std=c++17 -fPIC
endef
define $(package)_preprocess_cmds
echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <arflags>\"$($(package)_arflags)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
endef
define $(package)_config_cmds
./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries)
endef
define $(package)_build_cmds
./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) stage
endef
define $(package)_stage_cmds
./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) install
endef
EOF
sed -i 's/^ /\t/' contrib/depends/packages/boost.mk
- name: Build Dependencies
run: |
cd contrib/depends
make HOST=${{ matrix.target }} -j$(nproc)
- name: Build Wownero Core
run: |
PREFIX=$(pwd)/contrib/depends/${{ matrix.target }}
mkdir build && cd build
export CXXFLAGS="-D_GNU_SOURCE"
export CFLAGS="-D_GNU_SOURCE"
STATIC_RUNTIME="ON"
if [[ "${{ matrix.target }}" == *"apple"* ]]; then
STATIC_RUNTIME="OFF"
perl -pi -e 's/locale//g' ../CMakeLists.txt
perl -pi -e 's/locale//g' ../external/monero/CMakeLists.txt
fi
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../contrib/depends/${{ matrix.target }}/share/toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_STATIC=ON \
-DBoost_USE_STATIC_RUNTIME=$STATIC_RUNTIME
make -j$(nproc)
# -----------------------------------------------------------------------
# 2. FAIL-SAFE (Now includes Libevent)
# -----------------------------------------------------------------------
- name: Ensure Static Libs Exist
run: |
LIB_DIR="$(pwd)/contrib/depends/${{ matrix.target }}/lib"
INC_DIR="$(pwd)/contrib/depends/${{ matrix.target }}/include"
TOOLCHAIN="$(pwd)/contrib/depends/${{ matrix.target }}/share/toolchain.cmake"
mkdir -p "$LIB_DIR"
mkdir -p "$INC_DIR"
# --- FAIL-SAFE 1: ZSTD ---
if [ ! -f "$LIB_DIR/libzstd.a" ]; then
echo "Zstd missing! Activating Fail-Safe Build..."
mkdir -p temp_zstd && cd temp_zstd
curl -L -o zstd.tar.gz https://github.com/facebook/zstd/releases/download/v1.5.5/zstd-1.5.5.tar.gz
tar -xf zstd.tar.gz && cd zstd-1.5.5/build/cmake
cmake . -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
-DCMAKE_INSTALL_PREFIX="$(pwd)/../../inst" \
-DCMAKE_BUILD_TYPE=Release \
-DZSTD_BUILD_STATIC=ON -DZSTD_BUILD_SHARED=OFF \
-DZSTD_BUILD_PROGRAMS=OFF -DZSTD_BUILD_TESTS=OFF
make -j$(nproc)
if [ -f lib/libzstd.a ]; then cp lib/libzstd.a "$LIB_DIR/"; fi
if [ -f lib/libzstdstatic.a ]; then cp lib/libzstdstatic.a "$LIB_DIR/libzstd.a"; fi
cp ../../lib/zstd.h "$INC_DIR/"
cd ../../..
fi
# --- FAIL-SAFE 2: ZLIB ---
if [ ! -f "$LIB_DIR/libz.a" ]; then
echo "Zlib missing! Activating Fail-Safe Build..."
mkdir -p temp_zlib && cd temp_zlib
curl -L -o zlib.tar.gz https://zlib.net/zlib-1.3.1.tar.gz
tar -xf zlib.tar.gz && cd zlib-1.3.1
cmake . -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
-DCMAKE_INSTALL_PREFIX="$(pwd)/inst" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF
make -j$(nproc)
if [ -f libz.a ]; then cp libz.a "$LIB_DIR/"; fi
if [ -f libzlibstatic.a ]; then cp libzlibstatic.a "$LIB_DIR/libz.a"; fi
cp zlib.h "$INC_DIR/"
cp zconf.h "$INC_DIR/"
cd ../..
fi
# --- FAIL-SAFE 3: LIBEVENT (The Fix) ---
if [ ! -f "$LIB_DIR/libevent.a" ]; then
echo "Libevent missing! Activating Fail-Safe Build..."
mkdir -p temp_event && cd temp_event
curl -L -o libevent.tar.gz https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz
tar -xf libevent.tar.gz && cd libevent-2.1.12-stable
cmake . -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
-DCMAKE_INSTALL_PREFIX="$(pwd)/inst" \
-DCMAKE_BUILD_TYPE=Release \
-DEVENT__DISABLE_OPENSSL=ON \
-DEVENT__DISABLE_MBEDTLS=ON \
-DEVENT__DISABLE_TESTS=ON \
-DEVENT__DISABLE_SAMPLES=ON \
-DEVENT__LIBRARY_TYPE=STATIC
make -j$(nproc)
# Locate and copy the static lib (name might vary, grab any .a)
find . -name "libevent.a" -exec cp {} "$LIB_DIR/" \;
find . -name "libevent_core.a" -exec cp {} "$LIB_DIR/" \;
find . -name "libevent_extra.a" -exec cp {} "$LIB_DIR/" \;
# Also copy headers
mkdir -p "$INC_DIR/event2"
cp -r include/event2/* "$INC_DIR/event2/"
cd ../..
fi
- name: Package Artifacts
run: |
LIB_DIR="contrib/depends/${{ matrix.target }}/lib"
INC_DIR="contrib/depends/${{ matrix.target }}/include"
mkdir -p output/lib output/include output/bin
find build/bin -type f -exec cp -v {} output/bin/ \;
cp -v $LIB_DIR/*.a output/lib/
# Final Verification (The "Stop if Fucked" check)
ls -l output/lib/libz*.a
if [ ! -f output/lib/libzstd.a ]; then echo "FATAL: libzstd.a missing"; exit 1; fi
if [ ! -f output/lib/libz.a ]; then echo "FATAL: libz.a missing"; exit 1; fi
# Check for ANY libevent static lib (it might be libevent_core.a etc)
if [ -z "$(find output/lib -name 'libevent*.a')" ]; then
echo "FATAL: libevent.a missing (checked libevent*.a)"
exit 1
fi
cp -r src output/include/wownero-src
cp -r $INC_DIR/* output/include/
tar -czf wownero-core-${{ matrix.target }}.tar.gz -C output .
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: wownero-core-${{ matrix.target }}
path: wownero-core-${{ matrix.target }}.tar.gz
release:
needs: build-all
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Download Artifacts
uses: actions/download-artifact@v3
- name: Publish Release
uses: softprops/action-gh-release@v1
with:
files: |
wownero-core-*/wownero-core-*.tar.gz

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
custom: https://www.getmonero.org/get-started/contributing/

184
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,184 @@
name: ci/gh-actions/cli
on:
push:
pull_request:
paths-ignore:
- 'docs/**'
- '**/README.md'
# 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'
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
CCACHE_SETTINGS: |
ccache --max-size=150M
ccache --set-config=compression=true
jobs:
build-macos:
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
build-windows:
runs-on: windows-latest
env:
CCACHE_TEMPDIR: C:\Users\runneradmin\.ccache-temp
CCACHE_DIR: C:\Users\runneradmin\.ccache
defaults:
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
# 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-ubuntu:
runs-on: ${{ matrix.os }}
env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
strategy:
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}}
libwallet-ubuntu:
runs-on: ubuntu-20.04
env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
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
test-ubuntu:
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
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.
source-archive:
runs-on: ubuntu-20.04
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 }}

106
.github/workflows/depends.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: ci/gh-actions/depends
on:
push:
pull_request:
paths-ignore:
- 'docs/**'
- '**/README.md'
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
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
strategy:
fail-fast: false
matrix:
toolchain:
- name: "RISCV 64bit"
host: "riscv64-linux-gnu"
packages: "python3 gperf g++-riscv64-linux-gnu"
- name: "ARM v7"
host: "arm-linux-gnueabihf"
packages: "python3 gperf g++-arm-linux-gnueabihf"
- name: "ARM v8"
host: "aarch64-linux-gnu"
packages: "python3 gperf g++-aarch64-linux-gnu"
- name: "i686 Win"
host: "i686-w64-mingw32"
packages: "python3 g++-mingw-w64-i686"
- name: "i686 Linux"
host: "i686-pc-linux-gnu"
packages: "gperf cmake g++-multilib python3-zmq"
- name: "Win64"
host: "x86_64-w64-mingw32"
packages: "cmake python3 g++-mingw-w64-x86-64"
- name: "x86_64 Linux"
host: "x86_64-unknown-linux-gnu"
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"
- 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"
- 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
with:
fetch-depth: 0
submodules: recursive
# Most volatile cache
- name: ccache
uses: actions/cache@v3
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
with:
path: contrib/depends/built
key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
restore-keys: |
depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
depends-${{ matrix.toolchain.host }}-
# Static cache
- name: OSX SDK cache
uses: actions/cache@v3
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)
- name: build
run: |
${{env.CCACHE_SETTINGS}}
make depends target=${{ matrix.toolchain.host }} -j2
- uses: actions/upload-artifact@v3
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*

49
.github/workflows/gitian.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: ci/gh-actions/gitian
on:
push:
tags:
- '*'
jobs:
build-gitian:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
operating-system:
- name: "Linux"
option: "l"
- name: "Windows"
option: "w"
- name: "Android"
option: "a"
- name: "FreeBSD"
option: "f"
- name: "macOS"
option: "m"
name: ${{ matrix.operating-system.name }}
steps:
- name: prepare
run: |
sudo apt update
curl -O https://raw.githubusercontent.com/monero-project/monero/${{ github.ref_name }}/contrib/gitian/gitian-build.py
chmod +x gitian-build.py
- name: setup
run: |
./gitian-build.py --setup --docker github-actions ${{ github.ref_name }}
- name: build
run: |
./gitian-build.py --docker --detach-sign --no-commit --build -j 3 -o ${{ matrix.operating-system.option }} github-actions ${{ github.ref_name }}
- name: post build
run: |
cd out/${{ github.ref_name }}
shasum -a256 *
echo \`\`\` >> $GITHUB_STEP_SUMMARY
shasum -a256 * >> $GITHUB_STEP_SUMMARY
echo \`\`\` >> $GITHUB_STEP_SUMMARY
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.operating-system.name }}
path: |
out/${{ github.ref_name }}/*

1
.gitmodules vendored
View File

@@ -5,6 +5,7 @@
path = external/rapidjson
url = https://github.com/Tencent/rapidjson
[submodule "external/trezor-common"]
active = false
path = external/trezor-common
url = https://github.com/trezor/trezor-common.git
[submodule "external/supercop"]

View File

@@ -219,7 +219,7 @@ function(forbid_undefined_symbols)
file(MAKE_DIRECTORY "${TEST_PROJECT}")
file(WRITE "${TEST_PROJECT}/CMakeLists.txt"
[=[
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.1)
project(test)
option(EXPECT_SUCCESS "" ON)
file(WRITE "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
@@ -367,7 +367,7 @@ if(NOT MANUAL_SUBMODULES)
message(STATUS "Checking submodules")
check_submodule(external/miniupnp)
check_submodule(external/rapidjson)
check_submodule(external/trezor-common)
#check_submodule(external/trezor-common)
check_submodule(external/randomwow)
check_submodule(external/supercop)
endif()
@@ -406,7 +406,7 @@ option(BOOST_IGNORE_SYSTEM_PATHS "Ignore boost system paths for local boost inst
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
enable_testing()
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." ON)
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." OFF)
option(BUILD_TESTS "Build tests." OFF)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEFAULT_BUILD_DEBUG_UTILITIES ON)
@@ -1116,19 +1116,7 @@ if(MINGW)
if(DEPENDS)
set(ICU_LIBRARIES icuio icui18n icuuc icudata icutu iconv)
else()
# This is an extremely ugly hack to get around Boost not being built with static ICU.
# We reported the issue, we are waiting for upstream to fix this issue: https://github.com/boostorg/boost/issues/1079#issue-3384962885
# This hack links shared ICU libs to avoid linker errors we get in MSYS2 compilation (undefined symbols to ICU).
set(OLD_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a")
find_library(ICUIO_LIBRARIES NAMES icuio REQUIRED)
find_library(ICUIN_LIBRARIES NAMES icuin REQUIRED)
find_library(ICUUC_LIBRARIES NAMES icuuc REQUIRED)
find_library(ICUDT_LIBRARIES NAMES icudt REQUIRED)
find_library(ICUTU_LIBRARIES NAMES icutu REQUIRED)
find_library(ICONV_LIBRARIES NAMES iconv REQUIRED)
set(ICU_LIBRARIES ${ICUIO_LIBRARIES} ${ICUIN_LIBRARIES} ${ICUUC_LIBRARIES} ${ICUDT_LIBRARIES} ${ICUTU_LIBRARIES} ${ICONV_LIBRARIES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
set(ICU_LIBRARIES icuio icuin icuuc icudt icutu iconv)
endif()
elseif(APPLE OR OPENBSD OR ANDROID)
set(EXTRA_LIBRARIES "")

View File

@@ -41,26 +41,26 @@ RUN set -ex && \
rm -rf /var/lib/apt
COPY --from=builder /src/build/x86_64-linux-gnu/release/bin /usr/local/bin/
# Create monero user
RUN adduser --system --group --disabled-password monero && \
mkdir -p /wallet /home/monero/.bitmonero && \
chown -R monero:monero /home/monero/.bitmonero && \
chown -R monero:monero /wallet
# Create wownero user
RUN adduser --system --group --disabled-password wownero && \
mkdir -p /wallet /home/wownero/.wownero && \
chown -R wownero:wownero /home/wownero/.wownero && \
chown -R wownero:wownero /wallet
# Contains the blockchain
VOLUME /home/monero/.bitmonero
VOLUME /home/wownero/.wownero
# Generate your wallet via accessing the container and run:
# cd /wallet
# monero-wallet-cli
# wownero-wallet-cli
VOLUME /wallet
EXPOSE 18080
EXPOSE 18081
EXPOSE 34567
EXPOSE 34568
# switch to user monero
USER monero
# switch to user wownero
USER wownero
ENTRYPOINT ["monerod"]
CMD ["--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"]
ENTRYPOINT ["wownerod"]
CMD ["--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=34567", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=34568", "--non-interactive", "--confirm-external-bind"]

View File

@@ -44,7 +44,7 @@ else
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
endif
all: release-minimal
all: release-all
depends:
cd contrib/depends && $(MAKE) HOST=$(target) && cd ../.. && mkdir -p build/$(target)/release
@@ -100,18 +100,11 @@ release-test:
release-all:
mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
release-static:
mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
release-minimal:
@echo "Starting minimal Wownero build... for full build, run: make release-all"
mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -Wno-dev -D BUILD_TAG="minimal" -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTS=OFF -D BUILD_DOCUMENTATION=OFF -D BUILD_DEBUG_UTILITIES=OFF -D USE_DEVICE_TREZOR=OFF -D TREZOR_DEBUG=OFF -D BUILD_GUI_DEPS=OFF $(topdir) && $(MAKE) daemon simplewallet wallet_rpc_server
@echo "\n===== Build complete =====\n"
@echo "Binaries are available at: cd $(builddir)/release/bin\n"
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
coverage:
mkdir -p $(builddir)/debug

108
README.md
View File

@@ -1,6 +1,6 @@
# ~~Mo~~Wownero - Such privacy! Many coins! Wow!
[<img src="https://suchwow.xyz/uploads/J28THOqDiNkV.jpg">](https://suchwow.xyz/meme/157)
[<img src="https://suchwow.xyz/data/suchwow/image/to23moqn.jpeg">](https://suchwow.xyz/s/oh-really-9eda16b2/item)
## Introduction
@@ -10,39 +10,44 @@ Unlike Opposing Projects.
## Resources
- IRC: [OFTC #wownero](https://webchat.oftc.net/?channels=wownero)
- Web: [wownero.org](https://wownero.org)
- Twitter: [@w0wn3r0](https://twitter.com/w0wn3r0)
- Reddit: [/r/wownero](https://www.reddit.com/r/wownero)
- Mail: [wownero@wownero.org](mailto:wownero@wownero.org)
- Git: [codeberg.org/wownero/wownero](https://codeberg.org/wownero/wownero)
- Matrix General Chat Room: [#wownero-gen:wowne.ro](https://matrix.to/#/#wownero-gen:wowne.ro)
- IRC: [OFTC #wownero](https://webchat.oftc.net/?channels=wownero)
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
- Telegram: [t.me/wownero](https://t.me/wownero)
- Public Node Status: [monero.fail](https://monero.fail/?chain=wownero&network=mainnet)
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz)
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
## Exchanges
- [BasicSwap DEX](https://basicswapdex.com) ([Installation Guide](https://academy.particl.io/en/latest/basicswap-guides/basicswapguides_installation.html))
- [NonLogs](https://nonlogs.com/trade/WOW-BTC)
- [NonKYC](https://nonkyc.io/market/WOW_BTC)
- [AltQuick](https://altquick.com/market/Wownero)
- [Majestic Bank](https://majesticbank.sc)
- [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
## Wallets
- Wonero CLI Wallet: [codeberg.org/wownero/wownero](https://codeberg.org/wownero/wownero/releases)
- Wowlet Desktop Wallet: [codeberg.org/wownero/wowlet](https://codeberg.org/wownero/wowlet/releases)
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
- Cake Wallet [cakewallet.com](https://cakewallet.com)
## Blockchain Explorers
- https://explore.wownero.com
- https://explorer.suchwow.xyz
## Supporting the project
Wownero is a 100% community-sponsored endeavor. Supporting services are also graciously provided by sponsors:
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/macstadium.png"
alt="MacStadium"
height="100">](https://www.macstadium.com)
Developers are volunteers doing this mostly for shits and giggles. If you would like to support our shenanigans and stimulant addictions, please consider donating to the dev slush fund.
### Donation Addresses
@@ -84,7 +89,7 @@ Dates are provided in the format YYYY-MM-DD.
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.2.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
| 514,000 | 2023-04-01 | Kunty Karen | v0.11.0.0 | v0.11.4.0 | View tags, fee changes, adjusted dynamic block weight algorithm, multisig security fixes, RPC broadcast node donation sub-address, Limit tx_extra max size to ~1kb, 12-hour difficulty adjustment window
| 514,000 | 2023-04-01 | Kunty Karen | v0.11.0.0 | v0.11.3.0 | View tags, fee changes, adjusted dynamic block weight algorithm, multisig security fixes, RPC broadcast node donation sub-address, Limit tx_extra max size to ~1kb, 12-hour difficulty adjustment window
X's indicate that these details have not been determined as of commit date.
@@ -96,6 +101,14 @@ Packages are available for
yay -S wownero-git
* Gentoo - Russian hacking tool
emerge --noreplace eselect-repository
eselect repository enable monero
emaint sync -r monero
echo '*/*::monero ~amd64' >> /etc/portage/package.accept_keywords
emerge net-p2p/wownero
* NixOS
nix-shell -p wownero
@@ -107,41 +120,92 @@ Packaging for your favorite distribution would be a welcome contribution!
## Building from Source
* Docker
git clone https://codeberg.org/wownero/wownero && cd wownero
docker build -t git-wow:master -m 4g .
docker run -it -p 34567:34567 -p 34568:34568 -w /home/wownero/build/release/bin git-wow:master bash
* Arch Linux/Manjaro
sudo pacman -Syu --needed base-devel cmake boost openssl zeromq libpgm unbound libsodium libunwind xz readline expat gtest python3 ccache doxygen graphviz qt5-tools hidapi libusb protobuf systemd
sudo pacman -Syu --needed base-devel cmake boost openssl zeromq libpgm unbound libsodium libunwind xz readline expat gtest python3 ccache doxygen graphviz qt5-tools hidapi libusb protobuf systemd gcc13
git clone https://codeberg.org/wownero/wownero && cd wownero
make
export CC=gcc-13 CXX=g++-13
make -j2
* Debian/Ubuntu
sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev python3 ccache doxygen graphviz
sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev python3 ccache doxygen graphviz gcc-13 g++-13
git clone https://codeberg.org/wownero/wownero && cd wownero
make
CC="gcc-13" CXX="g++-13" make -j2
## Running Binaries
The build places the binary in `/build/<OS>/<BRANCH>/release/bin` sub-directory. To run in the
The build places the binary in `bin/` sub-directory within the build directory
from which cmake was invoked (repository root by default). To run in the
foreground:
./wownerod
./bin/wownerod
To list all available options, run `./wownerod --help`. Options can be specified either on the command line or in a configuration file passed by the `--config-file` argument. To specify an option in the configuration file, add a line with the syntax `argumentname=value`, where `argumentname` is the name of the argument without the leading dashes, for example, `log-level=1`.
To list all available options, run `./bin/wownerod --help`. Options can be
specified either on the command line or in a configuration file passed by the
`--config-file` argument. To specify an option in the configuration file, add
a line with the syntax `argumentname=value`, where `argumentname` is the name
of the argument without the leading dashes, for example, `log-level=1`.
To run in background:
./wownerod --detach
./bin/wownerod --log-file wownerod.log --detach
To run as a systemd service, copy
[wownerod.service](utils/systemd/wownerod.service) to `/etc/systemd/system/` and
[wow.conf](utils/conf/wow.conf) to `/etc/`. The [example
service](utils/systemd/wownerod.service) assumes that the user `wownero` exists
and its home is the data directory specified in the [example
config](wow.conf).
Once node is synced to network, run the CLI wallet by entering:
./wownero-wallet-cli
./bin/wownero-wallet-cli
Type `help` in CLI wallet to see standard commands (for advanced options, type `help_advanced`).
Copyright (c) 2014-2025 The Monero Project.
## Tor Anonymity Network
### Ubuntu
* `sudo apt-get update && sudo apt-get install tor -y`
* `sudo nano /etc/tor/torrc`
add the following:
```
HiddenServiceDir /var/lib/tor/wownero/
HiddenServicePort 34569 127.0.0.1:34569
HiddenServicePort 34566 127.0.0.1:34566
HiddenServiceVersion 3
```
save and close nano
* `sudo /etc/init.d/tor restart && sudo systemctl enable tor`
* copy [wow.conf](utils/conf/wow.conf) file and save it in same directory as `wownerod`.
* start wownerod like this:
```
./wownerod --config-file=wow.conf
```
* `sudo cat /var/lib/tor/wownero/hostname`
Copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero).
To share your node over p2p, uncomment first line of wownerod.conf and add your onion address.
### Access remote Tor node from CLI wallet
```
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
```
Copyright (c) 2014-2024 The Monero Project.
Portions Copyright (c) 2012-2013 The Cryptonote developers.

View File

@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
message(STATUS "Looking for ${flag} linker flag")
endif()
set(_cle_source ${monero_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "${flag}")

View File

@@ -55,10 +55,6 @@ if (USE_DEVICE_TREZOR)
set(Protobuf_FOUND 1) # override found if all rquired info was provided by variables
endif()
if (Protobuf_VERSION VERSION_GREATER_EQUAL 22.0)
add_definitions(-DPROTOBUF_HAS_ABSEIL)
endif()
if(TREZOR_DEBUG)
set(USE_DEVICE_TREZOR_DEBUG 1)
endif()

View File

@@ -21,24 +21,18 @@ host_toolchain:=$(HOST)-
endif
ifneq ($(DEBUG),)
release_type=debug
release_type=Debug
else
release_type=release
release_type=Release
endif
ifneq ($(TESTS),)
build_tests=ON
release_type=debug
release_type=Debug
else
build_tests=OFF
endif
ifeq ($(release_type),debug)
cmake_release_type=Debug
else
cmake_release_type=Release
endif
base_build_dir=$(BASEDIR)/work/build
base_staging_dir=$(BASEDIR)/work/staging
base_download_dir=$(BASEDIR)/work/download
@@ -185,7 +179,7 @@ $(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
-e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
-e 's|@debug@|$(DEBUG)|' \
-e 's|@release_type@|$(cmake_release_type)|' \
-e 's|@release_type@|$(release_type)|' \
-e 's|@build_tests@|$(build_tests)|' \
-e 's|@depends@|$(host_cmake)|' \
-e 's|@prefix@|$($(host_arch)_$(host_os)_prefix)|'\

View File

@@ -1,44 +1,36 @@
package=boost
$(package)_version=1.90.0
$(package)_download_path=https://archives.boost.io/release/$($(package)_version)/source/
$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.bz2
$(package)_sha256_hash=49551aff3b22cbc5c5a9ed3dbc92f0e23ea50a0f7325b0d198b705e8ee3fc305
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)_dependencies=libiconv
$(package)_patches=fix_aroptions.patch fix_arm_arch.patch
define $(package)_set_vars
$(package)_config_opts_release=variant=release
$(package)_config_opts_debug=variant=debug
$(package)_config_opts+=--layout=system --user-config=user-config.jam
$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
$(package)_config_opts_linux=threadapi=pthread runtime-link=static
# Darwin (macOS) Defaults
$(package)_config_opts_darwin=target-os=darwin runtime-link=shared
# Windows Defaults
$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
# Architecture Specifics
$(package)_config_opts_x86_64_mingw32=address-model=64
$(package)_config_opts_i686_mingw32=address-model=32
$(package)_config_opts_i686_linux=address-model=32 architecture=x86
# MACOS ARM64 FIX: Explicitly tell B2 this is ARM + Mach-O
$(package)_config_opts_x86_64_darwin=address-model=64
$(package)_config_opts_aarch64_darwin=address-model=64 architecture=arm binary-format=mach-o abi=aapcs
$(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=darwin
$(package)_archiver_darwin=$($(package)_libtool)
$(package)_config_libraries=atomic,chrono,date_time,filesystem,program_options,regex,serialization,system,thread,locale,context,coroutine
$(package)_cxxflags=-std=c++17 -fPIC
$(package)_config_opts_release=variant=release
$(package)_config_opts_debug=variant=debug
$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam
$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
$(package)_config_opts_linux=threadapi=pthread runtime-link=shared
$(package)_config_opts_android=threadapi=pthread runtime-link=static target-os=android
$(package)_config_opts_darwin=--toolset=darwin runtime-link=shared
$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
$(package)_config_opts_x86_64_mingw32=address-model=64
$(package)_config_opts_i686_mingw32=address-model=32
$(package)_config_opts_i686_linux=address-model=32 architecture=x86
$(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=darwin
$(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
endef
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/fix_aroptions.patch &&\
patch -p1 < $($(package)_patch_dir)/fix_arm_arch.patch &&\
echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <arflags>\"$($(package)_arflags)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
endef
@@ -52,4 +44,4 @@ endef
define $(package)_stage_cmds
./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) install
endef
endef

View File

@@ -1,9 +1,10 @@
package=hidapi
$(package)_version=0.15.0
$(package)_version=0.13.1
$(package)_download_path=https://github.com/libusb/hidapi/archive/refs/tags
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=5d84dec684c27b97b921d2f3b73218cb773cf4ea915caee317ac8fc73cef8136
$(package)_sha256_hash=476a2c9a4dc7d1fc97dd223b84338dbea3809a84caea2dcd887d9778725490e3
$(package)_linux_dependencies=libusb eudev
$(package)_patches=missing_win_include.patch
define $(package)_set_vars
$(package)_config_opts=--enable-static --disable-shared
@@ -16,7 +17,7 @@ $(package)_config_opts_linux+=--with-pic
endef
define $(package)_preprocess_cmds
./bootstrap
patch -p1 < $($(package)_patch_dir)/missing_win_include.patch && ./bootstrap
endef
define $(package)_config_cmds

View File

@@ -1,4 +1,4 @@
packages:=boost openssl expat libusb hidapi protobuf libiconv sodium zeromq unbound zlib zstd
packages:=boost openssl zeromq libiconv expat unbound
# ccache is useless in gitian builds
ifneq ($(GITIAN),1)

View File

@@ -1,21 +0,0 @@
package=zlib
$(package)_version=1.3.1
$(package)_download_path=https://zlib.net/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
define $(package)_set_vars
$(package)_config_opts=--static
endef
define $(package)_config_cmds
CHOST=${host} ./configure $($(package)_config_opts) --prefix=$($(package)_staging_prefix_dir)
endef
define $(package)_build_cmds
$(MAKE) libz.a
endef
define $(package)_stage_cmds
$(MAKE) install
endef

View File

@@ -1,14 +0,0 @@
package=zstd
$(package)_version=1.5.5
$(package)_download_path=https://github.com/facebook/zstd/releases/download/v$($(package)_version)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4
define $(package)_build_cmds
$(MAKE) -C lib libzstd.a
endef
define $(package)_stage_cmds
cp lib/libzstd.a $($(package)_staging_prefix_dir)/lib/
cp lib/zstd.h $($(package)_staging_prefix_dir)/include/
endef

View File

@@ -0,0 +1,21 @@
From a77b066311da42ed7654e39c0356a3b951b2e296 Mon Sep 17 00:00:00 2001
From: selsta <selsta@sent.at>
Date: Wed, 10 Nov 2021 02:28:54 +0100
Subject: [PATCH] windows: add missing include for mingw32
---
windows/hid.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/windows/hid.c b/windows/hid.c
index 24756a4..6d8394c 100644
--- a/windows/hid.c
+++ b/windows/hid.c
@@ -33,6 +33,7 @@ typedef LONG NTSTATUS;
#endif
#ifdef __MINGW32__
+#include <devpropdef.h>
#include <ntdef.h>
#include <winbase.h>
#endif

View File

@@ -38,6 +38,7 @@ 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);
}
}

View File

@@ -0,0 +1,96 @@
/*
* libEtPan! -- a mail stuff library
*
* Copyright (C) 2001, 2005 - DINH Viet Hoa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the libEtPan! project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* $Id: md5.h,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $
*/
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifndef MD5_H
#define MD5_H
#include "md5global.h"
namespace md5
{
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
static void MD5Init(MD5_CTX * context);
static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen );
static void MD5Final ( unsigned char digest[16], MD5_CTX *context );
inline bool md5( unsigned char *input, int ilen, unsigned char output[16] )
{
MD5_CTX ctx;
MD5Init( &ctx );
MD5Update( &ctx, input, ilen );
MD5Final( output, &ctx);
memwipe( &ctx, sizeof( MD5_CTX ));
return true;
}
}
#include "md5_l.inl"
#endif

View File

@@ -0,0 +1,352 @@
/*
* libEtPan! -- a mail stuff library
*
* Copyright (C) 2001, 2005 - DINH Viet Hoa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the libEtPan! project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* $Id: md5.c,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $
*/
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifdef _WIN32
# include <winsock2.h>
#else
# include <arpa/inet.h>
#endif
#include "md5global.h"
#include "md5_l.h"
namespace md5
{
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5_memcpy (POINTER output, POINTER input, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
static void MD5Transform (UINT4 state[4], unsigned char block[64]);
static unsigned char* PADDING()
{
static unsigned char local_PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
return local_PADDING;
}
/* F, G, H and I are basic MD5 functions.
*/
#ifdef I
/* This might be defined via NANA */
#undef I
#endif
#define MD5_M_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define MD5_M_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define MD5_M_H(x, y, z) ((x) ^ (y) ^ (z))
#define MD5_M_I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { (a) += MD5_M_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define GG(a, b, c, d, x, s, ac) { (a) += MD5_M_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define HH(a, b, c, d, x, s, ac) { (a) += MD5_M_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define II(a, b, c, d, x, s, ac) { (a) += MD5_M_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
static void MD5Init(MD5_CTX * context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the context.
*/
static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen )
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen)
{
MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)input, partLen );
MD5Transform( context->state, context->buffer );
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, (unsigned char*)&input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i );
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
| (((UINT4)input[j+3]) << 24);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
static void MD5Final ( unsigned char digest[16], MD5_CTX *context )
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING(), padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
memwipe ((POINTER)context, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (UINT4 state[4], unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
memwipe ((POINTER)x, sizeof (x));
}
}

View File

@@ -0,0 +1,77 @@
/*
* libEtPan! -- a mail stuff library
*
* Copyright (C) 2001, 2005 - DINH Viet Hoa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the libEtPan! project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $
*/
/* GLOBAL.H - RSAREF types and constants
*/
#ifndef MD5GLOBAL_H
#define MD5GLOBAL_H
namespace md5
{
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
//typedef unsigned long int UINT4;
typedef unsigned int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
}
#endif

View File

@@ -30,7 +30,6 @@
#ifdef __cplusplus
#include <sstream>
#include <string>
#include "easylogging++.h"
@@ -41,15 +40,9 @@
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
#define MAX_LOG_FILES 50
#define LOG_TO_STRING(x) \
std::stringstream ss; \
ss << x; \
const std::string str = ss.str();
#define MCLOG_TYPE(level, cat, color, type, x) do { \
if (el::Loggers::allowed(level, cat)) { \
LOG_TO_STRING(x); \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << str; \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while (0)
@@ -98,8 +91,7 @@
do { \
if (el::Loggers::allowed(level, cat)) { \
init; \
LOG_TO_STRING(x); \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << str; \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while(0)
#define MIDEBUG(init, x) IFLOG(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY, el::Color::Default, el::base::DispatchAction::NormalLog, init, x)

View File

@@ -47,7 +47,6 @@
#include <condition_variable>
#include <boost/asio.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/steady_timer.hpp>
@@ -65,7 +64,6 @@
#define MONERO_DEFAULT_LOG_CATEGORY "net"
#define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 1000
#define ABSTRACT_SERVER_SEND_QUE_MAX_BYTES_DEFAULT 100 * 1024 * 1024
namespace epee
{
@@ -78,13 +76,6 @@ 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(){}
};
/************************************************************************/
@@ -109,8 +100,8 @@ namespace net_utils
using ec_t = boost::system::error_code;
using handshake_t = boost::asio::ssl::stream_base::handshake_type;
using io_context_t = boost::asio::io_context;
using strand_t = io_context_t::strand;
using io_context_t = boost::asio::io_service;
using strand_t = boost::asio::io_service::strand;
using socket_t = boost::asio::ip::tcp::socket;
using network_throttle_t = epee::net_utils::network_throttle;
@@ -171,7 +162,6 @@ namespace net_utils
} read;
struct {
std::deque<epee::byte_slice> queue;
std::size_t total_bytes;
bool wait_consume;
} write;
};
@@ -270,33 +260,23 @@ 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),
plimit(nullptr),
response_soft_limit(ABSTRACT_SERVER_SEND_QUE_MAX_BYTES_DEFAULT),
stop_signal_sent(false)
: connection_basic_shared_state(), t_protocol_handler::config_type(), pfilter(nullptr), stop_signal_sent(false)
{}
i_connection_filter* pfilter;
i_connection_limit* plimit;
std::size_t response_soft_limit;
bool stop_signal_sent;
};
/// Construct a connection with the given io_context.
explicit connection( io_context_t& io_context,
/// Construct a connection with the given io_service.
explicit connection( boost::asio::io_service& io_service,
std::shared_ptr<shared_state> state,
t_connection_type connection_type,
epee::net_utils::ssl_support_t ssl_support,
t_connection_context&& initial = t_connection_context{});
epee::net_utils::ssl_support_t ssl_support);
explicit connection( io_context_t& io_context,
boost::asio::ip::tcp::socket&& sock,
explicit connection( boost::asio::ip::tcp::socket&& sock,
std::shared_ptr<shared_state> state,
t_connection_type connection_type,
epee::net_utils::ssl_support_t ssl_support,
t_connection_context&& initial = t_connection_context{});
epee::net_utils::ssl_support_t ssl_support);
@@ -326,7 +306,7 @@ namespace net_utils
virtual bool close();
virtual bool call_run_once_service_io();
virtual bool request_callback();
virtual io_context_t& get_io_context();
virtual boost::asio::io_service& get_io_service();
virtual bool add_ref();
virtual bool release();
//------------------------------------------------------
@@ -356,7 +336,7 @@ namespace net_utils
/// serve up files from the given directory.
boosted_tcp_server(t_connection_type connection_type);
explicit boosted_tcp_server(boost::asio::io_context& external_io_context, t_connection_type connection_type);
explicit boosted_tcp_server(boost::asio::io_service& external_io_service, t_connection_type connection_type);
~boosted_tcp_server();
std::map<std::string, t_connection_type> server_type_map;
@@ -369,7 +349,7 @@ namespace net_utils
const std::string port_ipv6 = "", const std::string address_ipv6 = "::", bool use_ipv6 = false, bool require_ipv4 = true,
ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
/// Run the server's io_context loop.
/// Run the server's io_service loop.
bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes());
/// wait for service workers stop
@@ -389,8 +369,6 @@ 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_response_soft_limit(std::size_t limit);
void set_default_remote(epee::net_utils::network_address remote)
{
@@ -401,7 +379,7 @@ namespace net_utils
try_connect_result_t try_connect(connection_ptr new_connection_l, const std::string& adr, const std::string& port, boost::asio::ip::tcp::socket &sock_, const boost::asio::ip::tcp::endpoint &remote_endpoint, const std::string &bind_ip, uint32_t conn_timeout, epee::net_utils::ssl_support_t ssl_support);
bool connect(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_connection_context& cn, const std::string& bind_ip = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
template<class t_callback>
bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, t_connection_context&& initial = t_connection_context{});
bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
boost::asio::ssl::context& get_ssl_context() noexcept
{
@@ -431,7 +409,7 @@ namespace net_utils
return connections_count;
}
boost::asio::io_context& get_io_context(){return io_context_;}
boost::asio::io_service& get_io_service(){return io_service_;}
struct idle_callback_conext_base
{
@@ -439,7 +417,7 @@ namespace net_utils
virtual bool call_handler(){return true;}
idle_callback_conext_base(boost::asio::io_context& io_serice):
idle_callback_conext_base(boost::asio::io_service& io_serice):
m_timer(io_serice)
{}
boost::asio::deadline_timer m_timer;
@@ -448,7 +426,7 @@ namespace net_utils
template <class t_handler>
struct idle_callback_conext: public idle_callback_conext_base
{
idle_callback_conext(boost::asio::io_context& io_serice, t_handler& h, uint64_t period):
idle_callback_conext(boost::asio::io_service& io_serice, t_handler& h, uint64_t period):
idle_callback_conext_base(io_serice),
m_handler(h)
{this->m_period = period;}
@@ -464,7 +442,7 @@ namespace net_utils
template<class t_handler>
bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms)
{
boost::shared_ptr<idle_callback_conext<t_handler>> ptr(new idle_callback_conext<t_handler>(io_context_, t_callback, timeout_ms));
boost::shared_ptr<idle_callback_conext<t_handler>> ptr(new idle_callback_conext<t_handler>(io_service_, t_callback, timeout_ms));
//needed call handler here ?...
ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period));
ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler<t_handler>, this, ptr));
@@ -483,14 +461,14 @@ namespace net_utils
}
template<class t_handler>
bool async_call(t_handler&& t_callback)
bool async_call(t_handler t_callback)
{
boost::asio::post(io_context_, std::forward<t_handler>(t_callback));
io_service_.post(t_callback);
return true;
}
private:
/// Run the server's io_context loop.
/// Run the server's io_service loop.
bool worker_thread();
/// Handle completion of an asynchronous accept operation.
void handle_accept_ipv4(const boost::system::error_code& e);
@@ -501,18 +479,18 @@ namespace net_utils
const std::shared_ptr<typename connection<t_protocol_handler>::shared_state> m_state;
/// The io_context used to perform asynchronous operations.
/// The io_service used to perform asynchronous operations.
struct worker
{
worker()
: io_context(), work(io_context.get_executor())
: io_service(), work(io_service)
{}
boost::asio::io_context io_context;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work;
boost::asio::io_service io_service;
boost::asio::io_service::work work;
};
std::unique_ptr<worker> m_io_context_local_instance;
boost::asio::io_context& io_context_;
std::unique_ptr<worker> m_io_service_local_instance;
boost::asio::io_service& io_service_;
/// Acceptor used to listen for incoming connections.
boost::asio::ip::tcp::acceptor acceptor_;

View File

@@ -31,12 +31,11 @@
//
#include <boost/asio/post.hpp>
#include <boost/foreach.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/chrono.hpp>
#include <boost/utility/value_init.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
#include <boost/thread/condition_variable.hpp> // TODO
@@ -146,19 +145,23 @@ namespace net_utils
if (m_state.timers.general.wait_expire) {
m_state.timers.general.cancel_expire = true;
m_state.timers.general.reset_expire = true;
m_timers.general.expires_after(
ec_t ec;
m_timers.general.expires_from_now(
std::min(
duration + (add ? (m_timers.general.expiry() - std::chrono::steady_clock::now()) : duration_t{}),
duration + (add ? m_timers.general.expires_from_now() : duration_t{}),
get_default_timeout()
)
),
ec
);
}
else {
m_timers.general.expires_after(
ec_t ec;
m_timers.general.expires_from_now(
std::min(
duration + (add ? (m_timers.general.expiry() - std::chrono::steady_clock::now()) : duration_t{}),
duration + (add ? m_timers.general.expires_from_now() : duration_t{}),
get_default_timeout()
)
),
ec
);
async_wait_timer();
}
@@ -199,7 +202,8 @@ namespace net_utils
return;
m_state.timers.general.cancel_expire = true;
m_state.timers.general.reset_expire = false;
m_timers.general.cancel();
ec_t ec;
m_timers.general.cancel(ec);
}
template<typename T>
@@ -221,8 +225,7 @@ namespace net_utils
m_state.data.read.buffer.size()
),
boost::asio::transfer_exactly(epee::net_utils::get_ssl_magic_size()),
boost::asio::bind_executor(
m_strand,
m_strand.wrap(
[this, self](const ec_t &ec, size_t bytes_transferred){
std::lock_guard<std::mutex> guard(m_state.lock);
m_state.socket.wait_read = false;
@@ -243,8 +246,7 @@ namespace net_utils
) {
m_state.ssl.enabled = false;
m_state.socket.handle_read = true;
boost::asio::post(
connection_basic::strand_,
connection_basic::strand_.post(
[this, self, bytes_transferred]{
bool success = m_handler.handle_recv(
reinterpret_cast<char *>(m_state.data.read.buffer.data()),
@@ -302,8 +304,7 @@ namespace net_utils
static_cast<shared_state&>(
connection_basic::get_state()
).ssl_options().configure(connection_basic::socket_, handshake);
boost::asio::post(
m_strand,
m_strand.post(
[this, self, on_handshake]{
connection_basic::socket_.async_handshake(
handshake,
@@ -312,7 +313,7 @@ namespace net_utils
m_state.ssl.forced ? 0 :
epee::net_utils::get_ssl_magic_size()
),
boost::asio::bind_executor(m_strand, on_handshake)
m_strand.wrap(on_handshake)
);
}
);
@@ -327,7 +328,7 @@ namespace net_utils
return;
}
auto self = connection<T>::shared_from_this();
if (speed_limit_is_enabled()) {
if (m_connection_type != e_connection_type_RPC) {
auto calc_duration = []{
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_in
@@ -344,7 +345,8 @@ namespace net_utils
};
const auto duration = calc_duration();
if (duration > duration_t{}) {
m_timers.throttle.in.expires_after(duration);
ec_t ec;
m_timers.throttle.in.expires_from_now(duration, ec);
m_state.timers.throttle.in.wait_expire = true;
m_timers.throttle.in.async_wait([this, self](const ec_t &ec){
std::lock_guard<std::mutex> guard(m_state.lock);
@@ -380,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
);
@@ -399,8 +401,7 @@ namespace net_utils
// writes until the connection terminates without deadlocking waiting
// for handle_recv.
m_state.socket.handle_read = true;
boost::asio::post(
connection_basic::strand_,
connection_basic::strand_.post(
[this, self, bytes_transferred]{
bool success = m_handler.handle_recv(
reinterpret_cast<char *>(m_state.data.read.buffer.data()),
@@ -427,18 +428,17 @@ namespace net_utils
m_state.data.read.buffer.data(),
m_state.data.read.buffer.size()
),
boost::asio::bind_executor(m_strand, on_read)
m_strand.wrap(on_read)
);
else
boost::asio::post(
m_strand,
m_strand.post(
[this, self, on_read]{
connection_basic::socket_.async_read_some(
boost::asio::buffer(
m_state.data.read.buffer.data(),
m_state.data.read.buffer.size()
),
boost::asio::bind_executor(m_strand, on_read)
m_strand.wrap(on_read)
);
}
);
@@ -454,7 +454,7 @@ namespace net_utils
return;
}
auto self = connection<T>::shared_from_this();
if (speed_limit_is_enabled()) {
if (m_connection_type != e_connection_type_RPC) {
auto calc_duration = [this]{
CRITICAL_REGION_LOCAL(
network_throttle_manager_t::m_lock_get_global_throttle_out
@@ -473,7 +473,8 @@ namespace net_utils
};
const auto duration = calc_duration();
if (duration > duration_t{}) {
m_timers.throttle.out.expires_after(duration);
ec_t ec;
m_timers.throttle.out.expires_from_now(duration, ec);
m_state.timers.throttle.out.wait_expire = true;
m_timers.throttle.out.async_wait([this, self](const ec_t &ec){
std::lock_guard<std::mutex> guard(m_state.lock);
@@ -497,12 +498,10 @@ namespace net_utils
if (m_state.socket.cancel_write) {
m_state.socket.cancel_write = false;
m_state.data.write.queue.clear();
m_state.data.write.total_bytes = 0;
state_status_check();
}
else if (ec.value()) {
m_state.data.write.queue.clear();
m_state.data.write.total_bytes = 0;
interrupt();
}
else {
@@ -514,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
);
@@ -527,11 +526,8 @@ namespace net_utils
start_timer(get_default_timeout(), true);
}
const std::size_t byte_count = m_state.data.write.queue.back().size();
assert(bytes_transferred == byte_count);
assert(bytes_transferred == m_state.data.write.queue.back().size());
m_state.data.write.queue.pop_back();
m_state.data.write.total_bytes -=
std::min(m_state.data.write.total_bytes, byte_count);
m_state.condition.notify_all();
start_write();
}
@@ -543,11 +539,10 @@ namespace net_utils
m_state.data.write.queue.back().data(),
m_state.data.write.queue.back().size()
),
boost::asio::bind_executor(m_strand, on_write)
m_strand.wrap(on_write)
);
else
boost::asio::post(
m_strand,
m_strand.post(
[this, self, on_write]{
boost::asio::async_write(
connection_basic::socket_,
@@ -555,7 +550,7 @@ namespace net_utils
m_state.data.write.queue.back().data(),
m_state.data.write.queue.back().size()
),
boost::asio::bind_executor(m_strand, on_write)
m_strand.wrap(on_write)
);
}
);
@@ -592,11 +587,10 @@ namespace net_utils
terminate();
}
};
boost::asio::post(
m_strand,
m_strand.post(
[this, self, on_shutdown]{
connection_basic::socket_.async_shutdown(
boost::asio::bind_executor(m_strand, on_shutdown)
m_strand.wrap(on_shutdown)
);
}
);
@@ -611,13 +605,15 @@ namespace net_utils
wait_socket = m_state.socket.cancel_handshake = true;
if (m_state.timers.throttle.in.wait_expire) {
m_state.timers.throttle.in.cancel_expire = true;
m_timers.throttle.in.cancel();
ec_t ec;
m_timers.throttle.in.cancel(ec);
}
if (m_state.socket.wait_read)
wait_socket = m_state.socket.cancel_read = true;
if (m_state.timers.throttle.out.wait_expire) {
m_state.timers.throttle.out.cancel_expire = true;
m_timers.throttle.out.cancel();
ec_t ec;
m_timers.throttle.out.cancel(ec);
}
if (m_state.socket.wait_write)
wait_socket = m_state.socket.cancel_write = true;
@@ -675,9 +671,8 @@ namespace net_utils
return;
if (m_state.timers.throttle.out.wait_expire)
return;
// \NOTE See on_terminating() comments
//if (m_state.socket.wait_write)
// return;
if (m_state.socket.wait_write)
return;
if (m_state.socket.wait_shutdown)
return;
if (m_state.protocol.wait_init)
@@ -735,13 +730,8 @@ namespace net_utils
return;
if (m_state.timers.throttle.out.wait_expire)
return;
// Writes cannot be canceled due to `async_write` being a "composed"
// handler. ASIO has new cancellation routines, not available in 1.66, to
// handle this situation. The problem is that if cancel is called after an
// intermediate handler is queued, the op will not check the cancel flag in
// our code, and will instead queue up another write.
//if (m_state.socket.wait_write)
// return;
if (m_state.socket.wait_write)
return;
if (m_state.socket.wait_shutdown)
return;
if (m_state.protocol.wait_init)
@@ -768,8 +758,6 @@ namespace net_utils
std::lock_guard<std::mutex> guard(m_state.lock);
if (m_state.status != status_t::RUNNING || m_state.socket.wait_handshake)
return false;
if (std::numeric_limits<std::size_t>::max() - m_state.data.write.total_bytes < message.size())
return false;
// Wait for the write queue to fall below the max. If it doesn't after a
// randomized delay, drop the connection.
@@ -787,14 +775,7 @@ namespace net_utils
std::uniform_int_distribution<>(5000, 6000)(rng)
);
};
// The bytes check intentionally does not include incoming message size.
// This allows for a soft overflow; a single http response will never fail
// this check, but multiple responses could. Clients can avoid this case
// by reading the entire response before making another request. P2P
// should never hit the MAX_BYTES check (when using default values).
if (m_state.data.write.queue.size() <= ABSTRACT_SERVER_SEND_QUE_MAX_COUNT &&
m_state.data.write.total_bytes <= static_cast<shared_state&>(connection_basic::get_state()).response_soft_limit)
if (m_state.data.write.queue.size() <= ABSTRACT_SERVER_SEND_QUE_MAX_COUNT)
return true;
m_state.data.write.wait_consume = true;
bool success = m_state.condition.wait_for(
@@ -803,23 +784,14 @@ namespace net_utils
[this]{
return (
m_state.status != status_t::RUNNING ||
(
m_state.data.write.queue.size() <=
ABSTRACT_SERVER_SEND_QUE_MAX_COUNT &&
m_state.data.write.total_bytes <=
static_cast<shared_state&>(connection_basic::get_state()).response_soft_limit
)
m_state.data.write.queue.size() <=
ABSTRACT_SERVER_SEND_QUE_MAX_COUNT
);
}
);
m_state.data.write.wait_consume = false;
if (!success) {
// synchronize with intermediate writes on `m_strand`
auto self = connection<T>::shared_from_this();
boost::asio::post(m_strand, [this, self] {
std::lock_guard<std::mutex> guard(m_state.lock);
terminate();
});
terminate();
return false;
}
else
@@ -845,9 +817,7 @@ namespace net_utils
) {
if (!wait_consume())
return false;
const std::size_t byte_count = message.size();
m_state.data.write.queue.emplace_front(std::move(message));
m_state.data.write.total_bytes += byte_count;
start_write();
}
else {
@@ -857,7 +827,6 @@ namespace net_utils
m_state.data.write.queue.emplace_front(
message.take_slice(CHUNK_SIZE)
);
m_state.data.write.total_bytes += m_state.data.write.queue.front().size();
start_write();
}
}
@@ -891,7 +860,7 @@ namespace net_utils
ipv4_network_address{
uint32_t{
boost::asio::detail::socket_ops::host_to_network_long(
endpoint.address().to_v4().to_uint()
endpoint.address().to_v4().to_ulong()
)
},
endpoint.port()
@@ -904,13 +873,6 @@ 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 (is_income && limit && limit->is_host_limit(*real_remote))
return false;
ec_t ec;
#if !defined(_WIN32) || !defined(__i686)
connection_basic::socket_.next_layer().set_option(
@@ -973,34 +935,28 @@ namespace net_utils
io_context_t &io_context,
std::shared_ptr<shared_state> shared_state,
t_connection_type connection_type,
ssl_support_t ssl_support,
t_connection_context&& initial
ssl_support_t ssl_support
):
connection(
io_context,
socket_t{io_context},
std::move(socket_t{io_context}),
std::move(shared_state),
connection_type,
ssl_support,
std::move(initial)
ssl_support
)
{
}
template<typename T>
connection<T>::connection(
io_context_t &io_context,
socket_t &&socket,
std::shared_ptr<shared_state> shared_state,
t_connection_type connection_type,
ssl_support_t ssl_support,
t_connection_context&& initial
ssl_support_t ssl_support
):
connection_basic(io_context, std::move(socket), shared_state, ssl_support),
connection_basic(std::move(socket), shared_state, ssl_support),
m_handler(this, *shared_state, m_conn_context),
m_connection_type(connection_type),
m_io_context{io_context},
m_conn_context(std::move(initial)),
m_io_context{GET_IO_SERVICE(connection_basic::socket_)},
m_strand{m_io_context},
m_timers{m_io_context}
{
@@ -1066,7 +1022,7 @@ namespace net_utils
template<typename T>
bool connection<T>::speed_limit_is_enabled() const
{
return m_connection_type == e_connection_type_P2P;
return m_connection_type != e_connection_type_RPC;
}
template<typename T>
@@ -1119,7 +1075,7 @@ namespace net_utils
return false;
auto self = connection<T>::shared_from_this();
++m_state.protocol.wait_callback;
boost::asio::post(connection_basic::strand_, [this, self]{
connection_basic::strand_.post([this, self]{
m_handler.handle_qued_callback();
std::lock_guard<std::mutex> guard(m_state.lock);
--m_state.protocol.wait_callback;
@@ -1132,7 +1088,7 @@ namespace net_utils
}
template<typename T>
typename connection<T>::io_context_t &connection<T>::get_io_context()
typename connection<T>::io_context_t &connection<T>::get_io_service()
{
return m_io_context;
}
@@ -1172,10 +1128,10 @@ namespace net_utils
template<class t_protocol_handler>
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server( t_connection_type connection_type ) :
m_state(std::make_shared<typename connection<t_protocol_handler>::shared_state>()),
m_io_context_local_instance(new worker()),
io_context_(m_io_context_local_instance->io_context),
acceptor_(io_context_),
acceptor_ipv6(io_context_),
m_io_service_local_instance(new worker()),
io_service_(m_io_service_local_instance->io_service),
acceptor_(io_service_),
acceptor_ipv6(io_service_),
default_remote(),
m_stop_signal_sent(false), m_port(0),
m_threads_count(0),
@@ -1189,11 +1145,11 @@ namespace net_utils
}
template<class t_protocol_handler>
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server(boost::asio::io_context& extarnal_io_context, t_connection_type connection_type) :
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server(boost::asio::io_service& extarnal_io_service, t_connection_type connection_type) :
m_state(std::make_shared<typename connection<t_protocol_handler>::shared_state>()),
io_context_(extarnal_io_context),
acceptor_(io_context_),
acceptor_ipv6(io_context_),
io_service_(extarnal_io_service),
acceptor_(io_service_),
acceptor_ipv6(io_service_),
default_remote(),
m_stop_signal_sent(false), m_port(0),
m_threads_count(0),
@@ -1240,27 +1196,24 @@ namespace net_utils
std::string ipv4_failed = "";
std::string ipv6_failed = "";
boost::asio::ip::tcp::resolver resolver(io_context_);
try
{
const auto results = resolver.resolve(
address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::canonical_name
);
acceptor_.open(results.begin()->endpoint().protocol());
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_.open(endpoint.protocol());
#if !defined(_WIN32)
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
#endif
acceptor_.bind(*results.begin());
acceptor_.bind(endpoint);
acceptor_.listen();
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
m_port = binded_endpoint.port();
MDEBUG("start accept (IPv4)");
new_connection_.reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, m_state->ssl_options().support));
new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4, this,
boost::asio::placeholders::error));
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4, this,
boost::asio::placeholders::error));
}
catch (const std::exception &e)
{
@@ -1281,25 +1234,23 @@ namespace net_utils
try
{
if (port_ipv6 == 0) port_ipv6 = port; // default arg means bind to same port as ipv4
const auto results = resolver.resolve(
address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::canonical_name
);
acceptor_ipv6.open(results.begin()->endpoint().protocol());
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_ipv6.open(endpoint.protocol());
#if !defined(_WIN32)
acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
#endif
acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
acceptor_ipv6.bind(*results.begin());
acceptor_ipv6.bind(endpoint);
acceptor_ipv6.listen();
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
m_port_ipv6 = binded_endpoint.port();
MDEBUG("start accept (IPv6)");
new_connection_ipv6.reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, m_state->ssl_options().support));
new_connection_ipv6.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
acceptor_ipv6.async_accept(new_connection_ipv6->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
boost::asio::placeholders::error));
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
boost::asio::placeholders::error));
}
catch (const std::exception &e)
{
@@ -1363,7 +1314,7 @@ namespace net_utils
{
try
{
io_context_.run();
io_service_.run();
return true;
}
catch(const std::exception& ex)
@@ -1398,20 +1349,6 @@ 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>
void boosted_tcp_server<t_protocol_handler>::set_response_soft_limit(const std::size_t limit)
{
assert(m_state != nullptr); // always set in constructor
m_state->response_soft_limit = limit;
}
//---------------------------------------------------------------------------------
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();
@@ -1421,7 +1358,7 @@ namespace net_utils
while(!m_stop_signal_sent)
{
// Create a pool of threads to run all of the io_contexts.
// Create a pool of threads to run all of the io_services.
CRITICAL_REGION_BEGIN(m_threads_lock);
for (std::size_t i = 0; i < threads_count; ++i)
{
@@ -1513,7 +1450,7 @@ namespace net_utils
}
connections_.clear();
connections_mutex.unlock();
io_context_.stop();
io_service_.stop();
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::send_stop_signal()", void());
}
//---------------------------------------------------------------------------------
@@ -1544,7 +1481,6 @@ namespace net_utils
accept_function_pointer = &boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6;
}
bool accept_started = false;
try
{
if (!e)
@@ -1561,11 +1497,10 @@ namespace net_utils
(*current_new_connection)->setRpcStation(); // hopefully this is not needed actually
}
connection_ptr conn(std::move((*current_new_connection)));
(*current_new_connection).reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, conn->get_ssl_support()));
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, conn->get_ssl_support()));
current_acceptor->async_accept((*current_new_connection)->socket(),
boost::bind(accept_function_pointer, this,
boost::asio::placeholders::error));
accept_started = true;
boost::asio::socket_base::keep_alive opt(true);
conn->socket().set_option(opt);
@@ -1591,15 +1526,13 @@ namespace net_utils
catch (const std::exception &e)
{
MERROR("Exception in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e.what());
if (accept_started)
return;
}
// error path, if e or exception
assert(m_state != nullptr); // always set in constructor
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count);
misc_utils::sleep_no_w(100);
(*current_new_connection).reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, (*current_new_connection)->get_ssl_support()));
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, (*current_new_connection)->get_ssl_support()));
current_acceptor->async_accept((*current_new_connection)->socket(),
boost::bind(accept_function_pointer, this,
boost::asio::placeholders::error));
@@ -1608,9 +1541,9 @@ namespace net_utils
template<class t_protocol_handler>
bool boosted_tcp_server<t_protocol_handler>::add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote, epee::net_utils::ssl_support_t ssl_support)
{
if(std::addressof(get_io_context()) == std::addressof(sock.get_executor().context()))
if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock)))
{
connection_ptr conn(new connection<t_protocol_handler>(io_context_, std::move(sock), m_state, m_connection_type, ssl_support));
connection_ptr conn(new connection<t_protocol_handler>(std::move(sock), m_state, m_connection_type, ssl_support));
if(conn->start(false, 1 < m_threads_count, std::move(real_remote)))
{
conn->get_context(out);
@@ -1620,7 +1553,7 @@ namespace net_utils
}
else
{
MWARNING(out << " was not added, socket/io_context mismatch");
MWARNING(out << " was not added, socket/io_service mismatch");
}
return false;
}
@@ -1633,7 +1566,7 @@ namespace net_utils
sock_.open(remote_endpoint.protocol());
if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
{
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::make_address(bind_ip), 0);
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
boost::system::error_code ec;
sock_.bind(local_endpoint, ec);
if (ec)
@@ -1728,7 +1661,7 @@ namespace net_utils
{
TRY_ENTRY();
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support) );
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, ssl_support) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
@@ -1738,16 +1671,14 @@ namespace net_utils
bool try_ipv6 = false;
boost::asio::ip::tcp::resolver resolver(io_context_);
boost::asio::ip::tcp::resolver::results_type results{};
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
boost::system::error_code resolve_error;
boost::asio::ip::tcp::resolver::iterator iterator;
try
{
//resolving ipv4 address as ipv6 throws, catch here and move on
results = resolver.resolve(
boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
);
iterator = resolver.resolve(query, resolve_error);
}
catch (const boost::system::system_error& e)
{
@@ -1765,7 +1696,8 @@ namespace net_utils
std::string bind_ip_to_use;
if(results.empty())
boost::asio::ip::tcp::resolver::iterator end;
if(iterator == end)
{
if (!m_use_ipv6)
{
@@ -1785,11 +1717,11 @@ namespace net_utils
if (try_ipv6)
{
results = resolver.resolve(
boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
);
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
if(results.empty())
iterator = resolver.resolve(query6, resolve_error);
if(iterator == end)
{
_erro("Failed to resolve " << adr);
return false;
@@ -1809,8 +1741,6 @@ namespace net_utils
}
const auto iterator = results.begin();
MDEBUG("Trying to connect to " << adr << ":" << port << ", bind_ip = " << bind_ip_to_use);
//boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
@@ -1837,6 +1767,7 @@ namespace net_utils
if (r)
{
new_connection_l->get_context(conn_context);
//new_connection_l.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_pfilter));
}
else
{
@@ -1852,10 +1783,10 @@ namespace net_utils
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler> template<class t_callback>
bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support, t_connection_context&& initial)
bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support)
{
TRY_ENTRY();
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support, std::move(initial)) );
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, ssl_support) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
@@ -1865,16 +1796,14 @@ namespace net_utils
bool try_ipv6 = false;
boost::asio::ip::tcp::resolver resolver(io_context_);
boost::asio::ip::tcp::resolver::results_type results{};
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
boost::system::error_code resolve_error;
boost::asio::ip::tcp::resolver::iterator iterator;
try
{
//resolving ipv4 address as ipv6 throws, catch here and move on
results = resolver.resolve(
boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
);
iterator = resolver.resolve(query, resolve_error);
}
catch (const boost::system::system_error& e)
{
@@ -1890,7 +1819,8 @@ namespace net_utils
throw;
}
if(results.empty())
boost::asio::ip::tcp::resolver::iterator end;
if(iterator == end)
{
if (!try_ipv6)
{
@@ -1905,23 +1835,24 @@ namespace net_utils
if (try_ipv6)
{
results = resolver.resolve(
boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
);
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
if(results.empty())
iterator = resolver.resolve(query6, resolve_error);
if(iterator == end)
{
_erro("Failed to resolve " << adr);
return false;
}
}
boost::asio::ip::tcp::endpoint remote_endpoint(*results.begin());
boost::asio::ip::tcp::endpoint remote_endpoint(*iterator);
sock_.open(remote_endpoint.protocol());
if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
{
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::make_address(bind_ip.c_str()), 0);
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
boost::system::error_code ec;
sock_.bind(local_endpoint, ec);
if (ec)
@@ -1933,7 +1864,7 @@ namespace net_utils
}
}
boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(io_context_));
boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(io_service_));
//start deadline
sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout));
sh_deadline->async_wait([=](const boost::system::error_code& error)

View File

@@ -112,20 +112,21 @@ class connection_basic { // not-templated base class for rapid developmet of som
std::deque<byte_slice> m_send_que;
volatile bool m_is_multithreaded;
/// Strand to ensure the connection's handlers are not called concurrently.
boost::asio::io_context::strand strand_;
boost::asio::io_service::strand strand_;
/// Socket for the connection.
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
ssl_support_t m_ssl_support;
public:
// first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator
connection_basic(boost::asio::io_context &context, boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
connection_basic(boost::asio::io_context &context, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
connection_basic(boost::asio::ip::tcp::socket&& socket, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
connection_basic(boost::asio::io_service &io_service, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
virtual ~connection_basic() noexcept(false);
//! \return `shared_state` object passed in construction (ptr never changes).
connection_basic_shared_state& get_state() noexcept { return *m_state; /* verified in constructor */ }
connection_basic(boost::asio::io_service& io_service, std::atomic<long> &ref_sock_count, std::atomic<long> &sock_number, ssl_support_t ssl);
boost::asio::ip::tcp::socket& socket() { return socket_.next_layer(); }
ssl_support_t get_ssl_support() const { return m_ssl_support; }
@@ -134,7 +135,7 @@ class connection_basic { // not-templated base class for rapid developmet of som
bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {})
{
//m_state != nullptr verified in constructor
return m_state->ssl_options().handshake(strand_.context(), socket_, type, buffer);
return m_state->ssl_options().handshake(socket_, type, buffer);
}
template<typename MutableBufferSequence, typename ReadHandler>

View File

@@ -34,7 +34,6 @@
#include <string>
#include <utility>
#include <list>
#include <cstdint>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"

View File

@@ -32,7 +32,6 @@
#include <boost/optional/optional.hpp>
#include <string>
#include <unordered_map>
#include "net_utils_base.h"
#include "http_auth.h"
#include "http_base.h"
@@ -55,13 +54,8 @@ namespace net_utils
{
std::string m_folder;
std::vector<std::string> m_access_control_origins;
std::unordered_map<std::string, std::size_t> m_connections;
boost::optional<login> m_user;
size_t m_max_content_length{std::numeric_limits<size_t>::max()};
std::size_t m_connection_count{0};
std::size_t m_max_public_ip_connections{3};
std::size_t m_max_private_ip_connections{25};
std::size_t m_max_connections{100};
critical_section m_lock;
};
@@ -76,7 +70,7 @@ namespace net_utils
typedef http_server_config config_type;
simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context);
virtual ~simple_http_connection_handler();
virtual ~simple_http_connection_handler(){}
bool release_protocol()
{
@@ -92,7 +86,10 @@ namespace net_utils
{
return true;
}
bool after_init_connection();
bool after_init_connection()
{
return true;
}
virtual bool handle_recv(const void* ptr, size_t cb);
virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response);
@@ -149,7 +146,6 @@ namespace net_utils
protected:
i_service_endpoint* m_psnd_hndlr;
t_connection_context& m_conn_context;
bool m_initialized;
};
template<class t_connection_context>
@@ -216,6 +212,10 @@ namespace net_utils
}
void handle_qued_callback()
{}
bool after_init_connection()
{
return true;
}
private:
//simple_http_connection_handler::config_type m_stub_config;

View File

@@ -208,46 +208,11 @@ namespace net_utils
m_newlines(0),
m_bytes_read(0),
m_psnd_hndlr(psnd_hndlr),
m_conn_context(conn_context),
m_initialized(false)
m_conn_context(conn_context)
{
}
//--------------------------------------------------------------------------------------------
template<class t_connection_context>
simple_http_connection_handler<t_connection_context>::~simple_http_connection_handler()
{
try
{
if (m_initialized)
{
CRITICAL_REGION_LOCAL(m_config.m_lock);
if (m_config.m_connection_count)
--m_config.m_connection_count;
auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
if (elem != m_config.m_connections.end())
{
if (elem->second == 1 || elem->second == 0)
m_config.m_connections.erase(elem);
else
--(elem->second);
}
}
}
catch (...)
{}
}
//--------------------------------------------------------------------------------------------
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::after_init_connection()
{
CRITICAL_REGION_LOCAL(m_config.m_lock);
++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
++m_config.m_connection_count;
m_initialized = true;
return true;
}
//--------------------------------------------------------------------------------------------
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::set_ready_state()
{

View File

@@ -71,7 +71,7 @@
else if((query_info.m_URI == s_pattern) && (cond)) \
{ \
handled = true; \
uint64_t ticks = epee::misc_utils::get_tick_count(); \
uint64_t ticks = misc_utils::get_tick_count(); \
boost::value_initialized<command_type::request> req; \
bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
if (!parse_res) \
@@ -107,7 +107,7 @@
else if(query_info.m_URI == s_pattern) \
{ \
handled = true; \
uint64_t ticks = epee::misc_utils::get_tick_count(); \
uint64_t ticks = misc_utils::get_tick_count(); \
boost::value_initialized<command_type::request> req; \
bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \
if (!parse_res) \
@@ -117,7 +117,7 @@
response_info.m_response_comment = "Bad request"; \
return true; \
} \
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
uint64_t ticks1 = misc_utils::get_tick_count(); \
boost::value_initialized<command_type::response> resp;\
MINFO(m_conn_context << "calling " << s_pattern); \
bool res = false; \
@@ -129,7 +129,7 @@
response_info.m_response_comment = "Internal Server Error"; \
return true; \
} \
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
uint64_t ticks2 = misc_utils::get_tick_count(); \
epee::byte_slice buffer; \
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \

View File

@@ -33,7 +33,6 @@
#include <boost/thread.hpp>
#include <boost/bind/bind.hpp>
#include "cryptonote_config.h"
#include "net/abstract_tcp_server2.h"
#include "http_protocol_handler.h"
#include "net/http_server_handlers_map2.h"
@@ -45,8 +44,7 @@ namespace epee
{
template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base>
class http_server_impl_base: public net_utils::http::i_http_server_handler<t_connection_context>,
net_utils::i_connection_limit
class http_server_impl_base: public net_utils::http::i_http_server_handler<t_connection_context>
{
public:
@@ -54,7 +52,7 @@ namespace epee
: m_net_server(epee::net_utils::e_connection_type_RPC)
{}
explicit http_server_impl_base(boost::asio::io_context& external_io_service)
explicit http_server_impl_base(boost::asio::io_service& external_io_service)
: m_net_server(external_io_service)
{}
@@ -62,16 +60,8 @@ namespace epee
const std::string& bind_ipv6_address = "::", bool use_ipv6 = false, bool require_ipv4 = true,
std::vector<std::string> access_control_origins = std::vector<std::string>(),
boost::optional<net_utils::http::login> user = boost::none,
net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect,
const std::size_t max_public_ip_connections = DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP,
const std::size_t max_private_ip_connections = DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP,
const std::size_t max_connections = DEFAULT_RPC_MAX_CONNECTIONS,
const std::size_t response_soft_limit = DEFAULT_RPC_SOFT_LIMIT_SIZE)
net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect)
{
if (max_connections < max_public_ip_connections)
throw std::invalid_argument{"Max public IP connections cannot be more than max connections"};
if (max_connections < max_private_ip_connections)
throw std::invalid_argument{"Max private IP connections cannot be more than max connections"};
//set self as callback handler
m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this);
@@ -85,11 +75,6 @@ namespace epee
m_net_server.get_config_object().m_access_control_origins = std::move(access_control_origins);
m_net_server.get_config_object().m_user = std::move(user);
m_net_server.get_config_object().m_max_public_ip_connections = max_public_ip_connections;
m_net_server.get_config_object().m_max_private_ip_connections = max_private_ip_connections;
m_net_server.get_config_object().m_max_connections = max_connections;
m_net_server.set_response_soft_limit(response_soft_limit);
m_net_server.set_connection_limit(this);
MGINFO("Binding on " << bind_ip << " (IPv4):" << bind_port);
if (use_ipv6)
@@ -146,26 +131,6 @@ namespace epee
}
protected:
virtual bool is_host_limit(const net_utils::network_address& na) override final
{
auto& config = m_net_server.get_config_object();
CRITICAL_REGION_LOCAL(config.m_lock);
if (config.m_max_connections <= config.m_connection_count)
return true;
const bool is_private = na.is_loopback() || na.is_local();
const auto elem = config.m_connections.find(na.host_str());
if (elem != config.m_connections.end())
{
if (is_private)
return config.m_max_private_ip_connections <= elem->second;
else
return config.m_max_public_ip_connections <= elem->second;
}
return false;
}
net_utils::boosted_tcp_server<net_utils::http::http_custom_handler<t_connection_context> > m_net_server;
};
}

View File

@@ -200,7 +200,7 @@ public:
struct anvoke_handler: invoke_response_handler_base
{
anvoke_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command)
:m_cb(cb), m_timeout(timeout), m_con(con), m_timer(con.m_pservice_endpoint->get_io_context()), m_timer_started(false),
:m_cb(cb), m_timeout(timeout), m_con(con), m_timer(con.m_pservice_endpoint->get_io_service()), m_timer_started(false),
m_cancel_timer_called(false), m_timer_cancelled(false), m_command(command)
{
if(m_con.start_outer_call())

View File

@@ -34,7 +34,7 @@
#include <atomic>
#include <string>
#include <boost/version.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/ssl.hpp>
@@ -158,11 +158,11 @@ namespace net_utils
inline
try_connect_result_t try_connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout)
{
m_deadline.expires_after(timeout);
m_deadline.expires_from_now(timeout);
boost::unique_future<boost::asio::ip::tcp::socket> connection = m_connector(addr, port, m_deadline);
for (;;)
{
m_io_service.restart();
m_io_service.reset();
m_io_service.run_one();
if (connection.is_ready())
@@ -178,7 +178,7 @@ namespace net_utils
// SSL Options
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{
if (!m_ssl_options.handshake(m_io_service, *m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout))
if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout))
{
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{
@@ -285,7 +285,7 @@ namespace net_utils
try
{
m_deadline.expires_after(timeout);
m_deadline.expires_from_now(timeout);
// Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the
@@ -303,7 +303,7 @@ namespace net_utils
// Block until the asynchronous operation has completed.
while (ec == boost::asio::error::would_block)
{
m_io_service.restart();
m_io_service.reset();
m_io_service.run_one();
}
@@ -409,7 +409,7 @@ namespace net_utils
// Set a deadline for the asynchronous operation. Since this function uses
// a composed operation (async_read_until), the deadline applies to the
// entire operation, rather than individual reads from the socket.
m_deadline.expires_after(timeout);
m_deadline.expires_from_now(timeout);
// Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the
@@ -436,7 +436,7 @@ namespace net_utils
// Block until the asynchronous operation has completed.
while (ec == boost::asio::error::would_block && !m_shutdowned)
{
m_io_service.restart();
m_io_service.reset();
m_io_service.run_one();
}
@@ -495,7 +495,7 @@ namespace net_utils
// Set a deadline for the asynchronous operation. Since this function uses
// a composed operation (async_read_until), the deadline applies to the
// entire operation, rather than individual reads from the socket.
m_deadline.expires_after(timeout);
m_deadline.expires_from_now(timeout);
// Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the
@@ -580,7 +580,7 @@ namespace net_utils
return true;
}
boost::asio::io_context& get_io_service()
boost::asio::io_service& get_io_service()
{
return m_io_service;
}
@@ -607,7 +607,7 @@ namespace net_utils
// Check whether the deadline has passed. We compare the deadline against
// the current time since a new asynchronous operation may have moved the
// deadline before this actor had a chance to run.
if (m_deadline.expiry() <= std::chrono::steady_clock::now())
if (m_deadline.expires_at() <= std::chrono::steady_clock::now())
{
// The deadline has passed. The socket is closed so that any outstanding
// asynchronous operations are cancelled. This allows the blocked
@@ -628,11 +628,11 @@ namespace net_utils
void shutdown_ssl() {
// ssl socket shutdown blocks if server doesn't respond. We close after 2 secs
boost::system::error_code ec = boost::asio::error::would_block;
m_deadline.expires_after(std::chrono::milliseconds(2000));
m_deadline.expires_from_now(std::chrono::milliseconds(2000));
m_ssl_socket->async_shutdown(boost::lambda::var(ec) = boost::lambda::_1);
while (ec == boost::asio::error::would_block)
{
m_io_service.restart();
m_io_service.reset();
m_io_service.run_one();
}
// Ignore "short read" error
@@ -676,7 +676,7 @@ namespace net_utils
}
protected:
boost::asio::io_context m_io_service;
boost::asio::io_service m_io_service;
boost::asio::ssl::context m_ctx;
std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_ssl_socket;
std::function<connect_func> m_connector;
@@ -688,6 +688,119 @@ namespace net_utils
std::atomic<uint64_t> m_bytes_sent;
std::atomic<uint64_t> m_bytes_received;
};
/************************************************************************/
/* */
/************************************************************************/
class async_blocked_mode_client: public blocked_mode_client
{
public:
async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service)
{
// No deadline is required until the first socket operation is started. We
// set the deadline to positive infinity so that the actor takes no action
// until a specific deadline is set.
m_send_deadline.expires_at(boost::posix_time::pos_infin);
// Start the persistent actor that checks for deadline expiry.
check_send_deadline();
}
~async_blocked_mode_client()
{
m_send_deadline.cancel();
}
bool shutdown()
{
blocked_mode_client::shutdown();
m_send_deadline.cancel();
return true;
}
inline
bool send(const void* data, size_t sz)
{
try
{
/*
m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout));
// Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the
// operation is incomplete. Asio guarantees that its asynchronous
// operations will never fail with would_block, so any other value in
// ec indicates completion.
boost::system::error_code ec = boost::asio::error::would_block;
// Start the asynchronous operation itself. The boost::lambda function
// object is used as a callback and will update the ec variable when the
// operation completes. The blocking_udp_client.cpp example shows how you
// can use boost::bind rather than boost::lambda.
boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1);
// Block until the asynchronous operation has completed.
while(ec == boost::asio::error::would_block)
{
m_io_service.run_one();
}*/
boost::system::error_code ec;
size_t writen = write(data, sz, ec);
if (!writen || ec)
{
LOG_PRINT_L3("Problems at write: " << ec.message());
return false;
}else
{
m_send_deadline.expires_at(boost::posix_time::pos_infin);
}
}
catch(const boost::system::system_error& er)
{
LOG_ERROR("Some problems at connect, message: " << er.what());
return false;
}
catch(...)
{
LOG_ERROR("Some fatal problems.");
return false;
}
return true;
}
private:
boost::asio::deadline_timer m_send_deadline;
void check_send_deadline()
{
// Check whether the deadline has passed. We compare the deadline against
// the current time since a new asynchronous operation may have moved the
// deadline before this actor had a chance to run.
if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now())
{
// The deadline has passed. The socket is closed so that any outstanding
// asynchronous operations are cancelled. This allows the blocked
// connect(), read_line() or write_line() functions to return.
LOG_PRINT_L3("Timed out socket");
m_ssl_socket->next_layer().close();
// There is no longer an active deadline. The expiry is set to positive
// infinity so that the actor takes no action until a new deadline is set.
m_send_deadline.expires_at(boost::posix_time::pos_infin);
}
// Put the actor back to sleep.
m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this));
}
};
}
}

View File

@@ -34,7 +34,6 @@
#include <string>
#include <vector>
#include <boost/utility/string_ref.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/filesystem/path.hpp>
@@ -126,7 +125,6 @@ namespace net_utils
\note It is strongly encouraged that clients using `system_ca`
verification provide a non-empty `host` for rfc2818 verification.
\param io_context associated with `socket`.
\param socket Used in SSL handshake and verification
\param type Client or server
\param host This parameter is only used when
@@ -138,7 +136,6 @@ namespace net_utils
\return True if the SSL handshake completes with peer verification
settings. */
bool handshake(
boost::asio::io_context& io_context,
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
boost::asio::ssl::stream_base::handshake_type type,
boost::asio::const_buffer buffer = {},

View File

@@ -30,7 +30,7 @@
#define _NET_UTILS_BASE_H_
#include <boost/uuid/uuid.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/address_v6.hpp>
#include <typeinfo>
#include <type_traits>
@@ -47,12 +47,10 @@
#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(((uint32_t)a4)<<24))
#endif
/* Use the below function carefully. The executor and io_context are slightly
different concepts. */
#if BOOST_VERSION >= 107000
#define MONERO_GET_EXECUTOR(type) type . get_executor()
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
#else
#define MONERO_GET_EXECUTOR(type) type . get_io_context()
#define GET_IO_SERVICE(s) ((s).get_io_service())
#endif
namespace net
@@ -445,7 +443,7 @@ namespace net_utils
virtual bool send_done()=0;
virtual bool call_run_once_service_io()=0;
virtual bool request_callback()=0;
virtual boost::asio::io_context& get_io_context()=0;
virtual boost::asio::io_service& get_io_service()=0;
//protect from deletion connection object(with protocol instance) during external call "invoke"
virtual bool add_ref()=0;
virtual bool release()=0;

View File

@@ -46,13 +46,13 @@ namespace net_utils
class network_throttle : public i_network_throttle {
public:
private:
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

View File

@@ -26,8 +26,6 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <set>
#include <list>
#include <vector>

View File

@@ -1,4 +1,3 @@
#include <math.h>
#include "net/abstract_http_client.h"
#include "net/http_base.h"
#include "net/net_parse_helpers.h"
@@ -136,13 +135,6 @@ namespace http
http::url_content parsed{};
const bool r = parse_url(address, parsed);
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
if (parsed.port == 0)
{
if (parsed.schema == "http")
parsed.port = 80;
else if (parsed.schema == "https")
parsed.port = 443;
}
set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options));
return true;
}

View File

@@ -46,6 +46,12 @@
// TODO:
#include "net/network_throttle-detail.hpp"
#if BOOST_VERSION >= 107000
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
#else
#define GET_IO_SERVICE(s) ((s).get_io_service())
#endif
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.conn"
@@ -121,12 +127,12 @@ connection_basic_pimpl::connection_basic_pimpl(const std::string &name) : m_thro
int connection_basic_pimpl::m_default_tos;
// methods:
connection_basic::connection_basic(boost::asio::io_context &io_context, boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
:
m_state(std::move(state)),
mI( new connection_basic_pimpl("peer") ),
strand_(io_context),
socket_(io_context, get_context(m_state.get())),
strand_(GET_IO_SERVICE(sock)),
socket_(GET_IO_SERVICE(sock), get_context(m_state.get())),
m_want_close_connection(false),
m_was_shutdown(false),
m_is_multithreaded(false),
@@ -146,12 +152,12 @@ connection_basic::connection_basic(boost::asio::io_context &io_context, boost::a
_note("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_state->sock_count);
}
connection_basic::connection_basic(boost::asio::io_context &io_context, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
connection_basic::connection_basic(boost::asio::io_service &io_service, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
:
m_state(std::move(state)),
mI( new connection_basic_pimpl("peer") ),
strand_(io_context),
socket_(io_context, get_context(m_state.get())),
strand_(io_service),
socket_(io_service, get_context(m_state.get())),
m_want_close_connection(false),
m_was_shutdown(false),
m_is_multithreaded(false),

View File

@@ -149,5 +149,40 @@ 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
}
}
}

View File

@@ -63,11 +63,11 @@
#include <cassert>
#include <iterator>
#include <limits>
#include <openssl/evp.h>
#include <tuple>
#include <type_traits>
#include "hex.h"
#include "md5_l.h"
#include "string_coding.h"
/* This file uses the `u8` prefix and specifies all chars by ASCII numeric
@@ -114,8 +114,8 @@ namespace
void operator()(const T& arg) const
{
const boost::iterator_range<const char*> data(boost::as_literal(arg));
EVP_DigestUpdate(
ctx,
md5::MD5Update(
std::addressof(ctx),
reinterpret_cast<const std::uint8_t*>(data.begin()),
data.size()
);
@@ -126,25 +126,25 @@ namespace
}
void operator()(const epee::wipeable_string& arg) const
{
EVP_DigestUpdate(
ctx,
md5::MD5Update(
std::addressof(ctx),
reinterpret_cast<const std::uint8_t*>(arg.data()),
arg.size()
);
}
EVP_MD_CTX *ctx;
md5::MD5_CTX& ctx;
};
template<typename... T>
std::array<char, 32> operator()(const T&... args) const
{
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(), &EVP_MD_CTX_free);
EVP_DigestInit(ctx.get(), EVP_md5());
boost::fusion::for_each(std::tie(args...), update{ctx.get()});
md5::MD5_CTX ctx{};
md5::MD5Init(std::addressof(ctx));
boost::fusion::for_each(std::tie(args...), update{ctx});
std::array<std::uint8_t, 16> digest{{}};
EVP_DigestFinal(ctx.get(), digest.data(), NULL);
md5::MD5Final(digest.data(), std::addressof(ctx));
return epee::to_hex::array(digest);
}
};

View File

@@ -4,38 +4,22 @@ namespace epee
{
namespace net_utils
{
namespace
{
struct new_connection
{
boost::promise<boost::asio::ip::tcp::socket> result_;
boost::asio::ip::tcp::socket socket_;
template<typename T>
explicit new_connection(T&& executor)
: result_(), socket_(std::forward<T>(executor))
{}
};
}
boost::unique_future<boost::asio::ip::tcp::socket>
direct_connect::operator()(const std::string& addr, const std::string& port, boost::asio::steady_timer& timeout) const
{
// Get a list of endpoints corresponding to the server name.
//////////////////////////////////////////////////////////////////////////
boost::asio::ip::tcp::resolver resolver(MONERO_GET_EXECUTOR(timeout));
boost::asio::ip::tcp::resolver resolver(GET_IO_SERVICE(timeout));
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
bool try_ipv6 = false;
boost::asio::ip::tcp::resolver::results_type results{};
boost::asio::ip::tcp::resolver::iterator iterator;
boost::asio::ip::tcp::resolver::iterator end;
boost::system::error_code resolve_error;
try
{
results = resolver.resolve(
boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
);
if (results.empty())
iterator = resolver.resolve(query, resolve_error);
if(iterator == end) // Documentation states that successful call is guaranteed to be non-empty
{
// if IPv4 resolution fails, try IPv6. Unintentional outgoing IPv6 connections should only
// be possible if for some reason a hostname was given and that hostname fails IPv4 resolution,
@@ -53,20 +37,27 @@ namespace net_utils
}
try_ipv6 = true;
}
if (try_ipv6)
{
results = resolver.resolve(
boost::asio::ip::tcp::v6(), addr, port, boost::asio::ip::tcp::resolver::canonical_name
);
if (results.empty())
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
iterator = resolver.resolve(query6);
if (iterator == end)
throw boost::system::system_error{boost::asio::error::fault, "Failed to resolve " + addr};
}
//////////////////////////////////////////////////////////////////////////
struct new_connection
{
boost::promise<boost::asio::ip::tcp::socket> result_;
boost::asio::ip::tcp::socket socket_;
const auto shared = std::make_shared<new_connection>(MONERO_GET_EXECUTOR(timeout));
explicit new_connection(boost::asio::io_service& io_service)
: result_(), socket_(io_service)
{}
};
const auto shared = std::make_shared<new_connection>(GET_IO_SERVICE(timeout));
timeout.async_wait([shared] (boost::system::error_code error)
{
if (error != boost::system::errc::operation_canceled && shared && shared->socket_.is_open())
@@ -75,7 +66,7 @@ namespace net_utils
shared->socket_.close();
}
});
shared->socket_.async_connect(*results.begin(), [shared] (boost::system::error_code error)
shared->socket_.async_connect(*iterator, [shared] (boost::system::error_code error)
{
if (shared)
{

View File

@@ -92,13 +92,7 @@ namespace net_utils
}
return true;
}
static bool parse_port(const std::string& port_str, uint64_t& out_port)
{
out_port = 0;
return boost::conversion::try_lexical_convert(port_str, out_port) && out_port <= 65535;
}
bool parse_uri(const std::string uri, http::uri_content& content)
{
@@ -159,8 +153,7 @@ namespace net_utils
}
if(result[6].matched)
{
if (!parse_port(result[6].str(), content.port))
return false;
content.port = boost::lexical_cast<uint64_t>(result[6]);
}
if(result[7].matched)
{
@@ -198,8 +191,7 @@ namespace net_utils
}
if(result[6].matched)
{
if (!parse_port(result[6].str(), content.port))
return false;
content.port = boost::lexical_cast<uint64_t>(result[6]);
}
if(result[7].matched)
{

View File

@@ -29,7 +29,6 @@
#include <string.h>
#include <thread>
#include <boost/asio/post.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/cerrno.hpp>
#include <boost/filesystem/operations.hpp>
@@ -46,13 +45,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.ssl"
#if BOOST_VERSION >= 107300
#define MONERO_HOSTNAME_VERIFY boost::asio::ssl::host_name_verification
#else
#define MONERO_HOSTNAME_VERIFY boost::asio::ssl::rfc2818_verification
#endif
// openssl genrsa -out /tmp/KEY 4096
// openssl req -new -key /tmp/KEY -out /tmp/REQ
// openssl x509 -req -days 999999 -sha256 -in /tmp/REQ -signkey /tmp/KEY -out /tmp/CERT
@@ -534,7 +526,7 @@ void ssl_options_t::configure(
// preverified means it passed system or user CA check. System CA is never loaded
// when fingerprints are whitelisted.
const bool verified = preverified &&
(verification != ssl_verification_t::system_ca || host.empty() || MONERO_HOSTNAME_VERIFY(host)(preverified, ctx));
(verification != ssl_verification_t::system_ca || host.empty() || boost::asio::ssl::rfc2818_verification(host)(preverified, ctx));
if (!verified && !has_fingerprint(ctx))
{
@@ -552,7 +544,6 @@ void ssl_options_t::configure(
}
bool ssl_options_t::handshake(
boost::asio::io_context& io_context,
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
boost::asio::ssl::stream_base::handshake_type type,
boost::asio::const_buffer buffer,
@@ -564,11 +555,12 @@ bool ssl_options_t::handshake(
auto start_handshake = [&]{
using ec_t = boost::system::error_code;
using timer_t = boost::asio::steady_timer;
using strand_t = boost::asio::io_context::strand;
using strand_t = boost::asio::io_service::strand;
using socket_t = boost::asio::ip::tcp::socket;
auto &io_context = GET_IO_SERVICE(socket);
if (io_context.stopped())
io_context.restart();
io_context.reset();
strand_t strand(io_context);
timer_t deadline(io_context, timeout);
@@ -603,13 +595,13 @@ bool ssl_options_t::handshake(
state.result = ec;
if (!state.cancel_handshake) {
state.cancel_timer = true;
deadline.cancel();
ec_t ec;
deadline.cancel(ec);
}
};
deadline.async_wait(on_timer);
boost::asio::post(
strand,
strand.post(
[&]{
socket.async_handshake(
type,

View File

@@ -46,7 +46,7 @@
#include "misc_log_ex.h"
#include <boost/chrono.hpp>
#include "misc_language.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <algorithm>
@@ -186,23 +186,6 @@ 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();
@@ -213,11 +196,14 @@ 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 "
<< " " << output_history{m_history}
<< " " << history_str
);
}
@@ -303,6 +289,8 @@ 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 "
@@ -312,7 +300,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) << output_history{m_history} << " "
<< "History: " << std::setw(8) << history_str << " "
<< "m_last_sample_time=" << std::setw(8) << m_last_sample_time
);

View File

@@ -163,15 +163,11 @@ namespace string_tools
void set_module_name_and_folder(const std::string& path_to_process_)
{
boost::filesystem::path path_to_process;
boost::filesystem::path path_to_process = path_to_process_;
#ifdef _WIN32
// Convert to wide string to avoid codecvt errors with Unicode paths
std::wstring wpath = epee::string_tools::utf8_to_utf16(get_current_module_path());
path_to_process = boost::filesystem::path(wpath);
#else
path_to_process = boost::filesystem::path(path_to_process_);
#endif
path_to_process = get_current_module_path();
#endif
get_current_module_name() = path_to_process.filename().string();
get_current_module_folder() = path_to_process.parent_path().string();

View File

@@ -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.4.5
VERSION=v0.18.3.4
./dockrun.sh $VERSION
```

View File

@@ -133,7 +133,7 @@ Common setup part:
su - gitianuser
GH_USER=YOUR_GITHUB_USER_NAME
VERSION=v0.18.4.5
VERSION=v0.18.3.4
```
Where `GH_USER` is your GitHub user name and `VERSION` is the version tag you want to build.

View File

@@ -120,8 +120,8 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release
make ${MAKEOPTS}
chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin
chmod 644 bin/LICENSE bin/*.md
cp ../utils/conf/wow.conf bin
chmod 644 bin/wow.conf
DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2

View File

@@ -117,8 +117,8 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=ON
make ${MAKEOPTS}
chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin
chmod 644 bin/LICENSE bin/*.md
cp ../utils/conf/wow.conf bin
chmod 644 bin/wow.conf
DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2

View File

@@ -169,8 +169,8 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=${BACKCOMPAT_OPTION} -DCMAKE_SKIP_RPATH=ON
make ${MAKEOPTS}
chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin
chmod 644 bin/LICENSE bin/*.md
cp ../utils/conf/wow.conf bin
chmod 644 bin/wow.conf
DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2

View File

@@ -108,8 +108,8 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
make ${MAKEOPTS}
chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin
chmod 644 bin/LICENSE bin/*.md
cp ../utils/conf/wow.conf bin
chmod 644 bin/wow.conf
DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2

View File

@@ -127,7 +127,7 @@ script: |
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
make ${MAKEOPTS}
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin
cp ../utils/conf/wow.conf bin
DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip

View File

@@ -39,7 +39,6 @@ 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)

View File

@@ -1244,19 +1244,11 @@ std::string OS::currentHost(void) {
#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID
}
static bool endswith(const std::string &s, const std::string &ending)
{
return s.size() >= ending.size() && s.substr(s.size() - ending.size()) == ending;
}
bool OS::termSupportsColor(std::string& term) {
return term == "xterm" || term == "screen" || term == "linux" || term == "cygwin"
|| endswith(term, "-color") || endswith(term, "-256color");
}
bool OS::termSupportsColor(void) {
std::string term = getEnvironmentVariable("TERM", "");
return termSupportsColor(term);
return term == "xterm" || term == "xterm-color" || term == "xterm-256color"
|| term == "screen" || term == "linux" || term == "cygwin"
|| term == "screen-256color" || term == "screen.xterm-256color";
}
// DateTime
@@ -3065,9 +3057,8 @@ void Writer::triggerDispatch(void) {
}
if (m_proceed && m_level == Level::Fatal
&& !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) {
const std::string str = "Aborting application. Reason: Fatal log at [" + std::string(m_file) + ":" + std::to_string(m_line) + "]";
base::Writer(Level::Warning, Color::Default, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
<< str;
<< "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]";
std::stringstream reasonStream;
reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]"
<< " If you wish to disable 'abort on fatal log' please use "

View File

@@ -1210,9 +1210,7 @@ class OS : base::StaticClass {
///
/// @detail For android systems this is device name with its manufacturer and model seperated by hyphen
static std::string currentHost(void);
/// @brief Whether or not the named terminal supports colors
static bool termSupportsColor(std::string& term);
/// @brief Whether or not the process's current terminal supports colors
/// @brief Whether or not terminal supports colors
static bool termSupportsColor(void);
};
/// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str
@@ -3262,19 +3260,21 @@ class Writer : base::NoCopy {
const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
base::type::VerboseLevel verboseLevel = 0) :
m_msg(nullptr), m_level(level), m_color(color), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel),
m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction), m_sync(ELPP->lock()) {
m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) {
}
Writer(LogMessage* msg, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog) :
m_msg(msg), m_level(msg != nullptr ? msg->level() : Level::Unknown),
m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction), m_sync(ELPP->lock()) {
m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) {
}
virtual ~Writer(void) {
processDispatch();
}
Writer& operator<<(const std::string &log) {
template <typename T>
inline typename std::enable_if<std::is_integral<T>::value, Writer&>::type
operator<<(T log) {
#if ELPP_LOGGING_ENABLED
if (m_proceed) {
m_messageBuilder << log;
@@ -3283,6 +3283,26 @@ class Writer : base::NoCopy {
return *this;
}
template <typename T>
inline typename std::enable_if<!std::is_integral<T>::value, Writer&>::type
operator<<(const T& log) {
#if ELPP_LOGGING_ENABLED
if (m_proceed) {
m_messageBuilder << log;
}
#endif // ELPP_LOGGING_ENABLED
return *this;
}
inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) {
#if ELPP_LOGGING_ENABLED
if (m_proceed) {
m_messageBuilder << log;
}
#endif // ELPP_LOGGING_ENABLED
return *this;
}
inline operator bool() {
return true;
}
@@ -3303,7 +3323,6 @@ class Writer : base::NoCopy {
base::MessageBuilder m_messageBuilder;
base::DispatchAction m_dispatchAction;
std::vector<std::string> m_loggerIds;
base::threading::ScopedLock m_sync;
friend class el::Helpers;
void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true);
@@ -3599,9 +3618,8 @@ class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback {
ss << ELPP_LITERAL("]");
}
}
const std::string str = ss.str();
el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1,
m_data->loggerId().c_str()) << str;
m_data->loggerId().c_str()) << ss.str();
}
private:
const PerformanceTrackingData* m_data;

View File

@@ -106,15 +106,15 @@ endif()
add_subdirectory(cryptonote_protocol)
if(NOT IOS)
add_subdirectory(simplewallet)
add_subdirectory(gen_multisig)
add_subdirectory(gen_ssl_cert)
add_subdirectory(daemonizer)
add_subdirectory(daemon)
add_subdirectory(blockchain_utilities)
endif()
if(BUILD_DEBUG_UTILITIES)
add_subdirectory(debug_utilities)
add_subdirectory(blockchain_utilities)
add_subdirectory(gen_multisig)
add_subdirectory(gen_ssl_cert)
endif()
if(PER_BLOCK_CHECKPOINT)

View File

@@ -245,7 +245,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
if (tx.version > 1)
{
commitment = tx.rct_signatures.outPk[i].mask;
if (rct::is_rct_bp_plus_legacy(tx.rct_signatures.type))
if (rct::is_rct_bulletproof_plus(tx.rct_signatures.type))
commitment = rct::scalarmult8(commitment);
}
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,

View File

@@ -28,17 +28,13 @@
#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"
@@ -1325,54 +1321,6 @@ 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;
@@ -1399,18 +1347,6 @@ 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;
if (!boost::filesystem::exists(datafile))
boost::filesystem::ofstream(datafile).close(); // create the file to see if NTFS compression is enabled beforehand
if (!disable_ntfs_compression(datafile))
throw DB_ERROR("Database file is NTFS compressed and compression could not be disabled");
#endif
boost::optional<bool> is_hdd_result = tools::is_hdd(filename.c_str());
if (is_hdd_result)
{
@@ -4564,11 +4500,12 @@ 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;
boost::system::error_code ec{};
const boost::uintmax_t size = boost::filesystem::file_size(datafile, ec);
return (ec ? 0 : static_cast<uint64_t>(size));
if (!epee::file_io_utils::get_file_size(datafile.string(), size))
size = 0;
return size;
}
void BlockchainLMDB::fixup()

View File

@@ -174,9 +174,7 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
for(auto& tx_blob: block_entry.txs)
{
tx_verification_context tvc = AUTO_VAL_INIT(tvc);
CHECK_AND_ASSERT_THROW_MES(tx_blob.prunable_hash == crypto::null_hash,
"block entry must not contain pruned txs");
core.handle_incoming_tx(tx_blob.blob, tvc, relay_method::block, true);
core.handle_incoming_tx(tx_blob, tvc, relay_method::block, true);
if(tvc.m_verifivation_failed)
{
cryptonote::transaction transaction;
@@ -192,9 +190,8 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
// process block
block_verification_context bvc = {};
pool_supplement ps{};
core.handle_incoming_block(block_entry.block, pblocks.empty() ? NULL : &pblocks[blockidx++], bvc, ps, false); // <--- process block
core.handle_incoming_block(block_entry.block, pblocks.empty() ? NULL : &pblocks[blockidx++], bvc, false); // <--- process block
if(bvc.m_verifivation_failed)
{

Binary file not shown.

View File

@@ -184,10 +184,17 @@ namespace cryptonote
{
if (nettype == TESTNET)
{
ADD_CHECKPOINT2(0, "48ca7cd3c8de5b6a4d53d2861fbdaedca141553559f9be9520068053cda8430b", "0x1");
ADD_CHECKPOINT2(1000000, "46b690b710a07ea051bc4a6b6842ac37be691089c0f7758cfeec4d5fc0b4a258", "0x7aaad7153");
ADD_CHECKPOINT2(1058600, "12904f6b4d9e60fd875674e07147d2c83d6716253f046af7b894c3e81da7e1bd", "0x971efd119");
ADD_CHECKPOINT2(1450000, "87562ca6786f41556b8d5b48067303a57dc5ca77155b35199aedaeca1550f5a0", "0xa639e2930e");
return true;
}
if (nettype == STAGENET)
{
ADD_CHECKPOINT2(0, "76ee3cc98646292206cd3e86f74d88b4dcc1d937088645e9b0cbca84b7ce74eb", "0x1");
ADD_CHECKPOINT2(10000, "1f8b0ce313f8b9ba9a46108bfd285c45ad7c2176871fd41c3a690d4830ce2fd5", "0x1d73ba");
ADD_CHECKPOINT2(550000, "409f68cddd8e74b37469b41c1e61250d81c5776b42264f416d5d27c4626383ed", "0x5f3d4d03e");
return true;
}
ADD_CHECKPOINT2(1, "97f4ce4d7879b3bea54dcec738cd2ebb7952b4e9bb9743262310cd5fec749340", "0x2");
@@ -226,8 +233,7 @@ namespace cryptonote
ADD_CHECKPOINT2(489400, "b14f49eae77398117ea93435676100d8b655a804689f73a5a4d0d5e71160d603", "0x1123c39bb52f7e");
ADD_CHECKPOINT2(491200, "cedba73ad35ce7f51aaca2beb36dc32d79ecc716d146eb8211e6a815f3666c4a", "0x11334734abbd17");
ADD_CHECKPOINT2(497100, "2c4c70ac1ada94151f19d67ccf1aa4e846e6067f49f67c85cc03f78e768ea42b", "0x116906bc97a751");
ADD_CHECKPOINT2(760300, "50ce41518bb4bea392194c13d0a5ef4cbf01ffb84ba393131e910adb63e2d360", "0x18ef58d8abb8b3");
ADD_CHECKPOINT2(771100, "03e834788e1e33dbba9bc3431a81189cd655f9da80323a728fa0dae56a95145e", "0x192cdb615ada62");
ADD_CHECKPOINT2(691500, "ed8e2507c0938b7eab7b02eccfb3506aeb591e51fbf6cf145fcc60ea2d351025", "0x163a280f2ce8e3");
return true;
}

View File

@@ -47,6 +47,11 @@ using namespace epee;
static const char *DEFAULT_DNS_PUBLIC_ADDR[] =
{
"194.150.168.168", // CCC (Germany)
"80.67.169.40", // FDN (France)
"89.233.43.71", // http://censurfridns.dk (Denmark)
"109.69.8.51", // punCAT (Spain)
"193.58.251.251", // SkyDNS (Russia)
};
static boost::mutex instance_lock;
@@ -99,6 +104,8 @@ get_builtin_ds(void)
{
static const char * const ds[] =
{
". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n",
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n",
NULL
};
return ds;

View File

@@ -30,6 +30,7 @@
#include <atomic>
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
#include "file_io_utils.h"
#include "net/http_client.h"
#include "download.h"
@@ -72,11 +73,8 @@ namespace tools
{
boost::unique_lock<boost::mutex> lock(control->mutex);
std::ios_base::openmode mode = std::ios_base::out | std::ios_base::binary;
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)
uint64_t existing_size = 0;
if (epee::file_io_utils::get_file_size(control->path, existing_size) && existing_size > 0)
{
MINFO("Resuming downloading " << control->uri << " to " << control->path << " from " << existing_size);
mode |= std::ios_base::app;

View File

@@ -185,7 +185,7 @@ namespace
return false;
if (verify)
{
std::cout << "Confirm password: " << std::flush;
std::cout << "Confirm password: ";
if (!read_from_tty(pass2, hide_input))
return false;
if(pass1!=pass2)

View File

@@ -28,7 +28,6 @@
#pragma once
#include <cstdint>
#include <string>
#include <stdio.h>
#include <memory>

View File

@@ -34,7 +34,6 @@
#include "easylogging++/easylogging++.h"
#include <stdexcept>
#include <iomanip>
#ifdef USE_UNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>

View File

@@ -936,7 +936,7 @@ std::string get_nix_version_display_string()
}
boost::system::error_code ec;
const auto parsed_ip = boost::asio::ip::make_address(u_c.host, ec);
const auto parsed_ip = boost::asio::ip::address::from_string(u_c.host, ec);
if (ec) {
MDEBUG("Failed to parse '" << address << "' as IP address: " << ec.message() << ". Considering it not local");
return false;
@@ -1360,13 +1360,30 @@ std::string get_nix_version_display_string()
// importance.
static const uint32_t average_block_sizes[] =
{
23956, 8606, 6156, 5778, 6549, 10028, 10207, 5681, 12915, 13680, 11402,
9194, 12082, 10496, 11879, 10304, 10356, 8433, 8252, 12264, 7143, 8484,
9226, 8726, 6961, 6082, 4234, 3712, 4307, 4324, 6758, 13616, 11376, 4091,
3157, 4450, 2966, 2264, 2290, 2046, 2156, 1902, 1966, 2354, 2295, 2126, 1977,
1728, 1591, 1968, 1426, 1280, 1372, 1266, 1399, 2044, 1320, 1100, 1084, 1384,
1183, 2458, 1285, 1501, 1270, 1222, 1284, 1246, 1552, 1431, 1325, 1774, 2771,
2855, 1394, 1388, 2882 // Blocks 0 to 760,486 in August 2025
442, 1211, 1445, 1763, 2272, 8217, 5603, 9999, 16358, 10805, 5290, 4362,
4325, 5584, 4515, 5008, 4789, 5196, 7660, 3829, 6034, 2925, 3762, 2545,
2437, 2553, 2167, 2761, 2015, 1969, 2350, 1731, 2367, 2078, 2026, 3518,
2214, 1908, 1780, 1640, 1976, 1647, 1921, 1716, 1895, 2150, 2419, 2451,
2147, 2327, 2251, 1644, 1750, 1481, 1570, 1524, 1562, 1668, 1386, 1494,
1637, 1880, 1431, 1472, 1637, 1363, 1762, 1597, 1999, 1564, 1341, 1388,
1530, 1476, 1617, 1488, 1368, 1906, 1403, 1695, 1535, 1598, 1318, 1234,
1358, 1406, 1698, 1554, 1591, 1758, 1426, 2389, 1946, 1533, 1308, 2701,
1525, 1653, 3580, 1889, 2913, 8164, 5154, 3762, 3356, 4360, 3589, 4844,
4232, 3781, 3882, 5924, 10790, 7185, 7442, 8214, 8509, 7484, 6939, 7391,
8210, 15572, 39680, 44810, 53873, 54639, 68227, 63428, 62386, 68504,
83073, 103858, 117573, 98089, 96793, 102337, 94714, 129568, 251584,
132026, 94579, 94516, 95722, 106495, 121824, 153983, 162338, 136608,
137104, 109872, 91114, 84757, 96339, 74251, 94314, 143216, 155837,
129968, 120201, 109913, 101588, 97332, 104611, 95310, 93419, 113345,
100743, 92152, 57565, 22533, 37564, 21823, 19980, 18277, 18402, 14344,
12142, 15842, 13677, 17631, 18294, 22270, 41422, 39296, 36688, 33512,
33831, 27582, 22276, 27516, 27317, 25505, 24426, 20566, 23045, 26766,
28185, 26169, 27011, 28642, 34994, 34442, 30682, 34357, 31640, 41167,
41301, 48616, 51075, 55061, 49909, 44606, 47091, 53828, 42520, 39023,
55245, 56145, 51119, 60398, 71821, 48142, 60310, 56041, 54176, 66220,
56336, 55248, 56656, 63305, 54029, 77136, 71902, 71618, 83587, 81068,
69062, 54848, 53681, 53555,
50616 // Blocks 2,400,000 to 2,409,999 in July 2021
};
const uint64_t block_range_size = 10000;

View File

@@ -33,7 +33,6 @@
#include <cstddef>
#include <cstring>
#include <functional>
#include <memory>
#include <sodium/crypto_verify_32.h>
#define CRYPTO_MAKE_COMPARABLE(type) \
@@ -61,18 +60,14 @@ 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) { \
std::size_t h; \
memcpy(&h, std::addressof(_v), sizeof(h)); \
return h; \
return reinterpret_cast<const std::size_t &>(_v); \
} \
} \
namespace std { \
template<> \
struct hash<crypto::type> { \
std::size_t operator()(const crypto::type &_v) const { \
std::size_t h; \
memcpy(&h, std::addressof(_v), sizeof(h)); \
return h; \
return reinterpret_cast<const std::size_t &>(_v); \
} \
}; \
}

View File

@@ -30,9 +30,8 @@
#pragma once
#include <iostream>
#include <stddef.h>
#include <stdexcept>
#include <iostream>
#include "common/pod-class.h"
#include "generic-ops.h"
@@ -71,20 +70,11 @@ namespace crypto {
return h;
}
static constexpr void cn_variant1_check(const std::size_t length, const int variant)
{
// see VARIANT1_CHECK in slow-hash.c
if (variant == 1 && length < 43)
throw std::logic_error("Cryptonight variant 1 is undefined for inputs of less than 43 bytes");
}
inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) {
cn_variant1_check(length, variant);
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 0/*prehashed*/, height);
}
inline void cn_slow_hash_prehashed(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) {
cn_variant1_check(length, variant);
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 1/*prehashed*/, height);
}

View File

@@ -152,17 +152,6 @@ DISABLE_VS_WARNINGS(4244 4345)
m_keys.m_multisig_keys.clear();
}
//-----------------------------------------------------------------
void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
{
// make sure derived spend public key matches saved public spend key
crypto::public_key spend_public_key;
crypto::secret_key_to_public_key(spend_secret_key, spend_public_key);
CHECK_AND_ASSERT_THROW_MES(m_keys.m_account_address.m_spend_public_key == spend_public_key,
"Unexpected derived public spend key");
m_keys.m_spend_secret_key = spend_secret_key;
}
//-----------------------------------------------------------------
crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
{
crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);

View File

@@ -95,7 +95,6 @@ namespace cryptonote
bool store(const std::string& file_path);
void forget_spend_key();
void set_spend_key(const crypto::secret_key& spend_secret_key);
const std::vector<crypto::secret_key> &get_multisig_keys() const { return m_keys.m_multisig_keys; }
void encrypt_keys(const crypto::chacha_key &key) { m_keys.encrypt(key); }

View File

@@ -29,7 +29,6 @@
#include "connection_context.h"
#include <boost/optional/optional.hpp>
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "p2p/p2p_protocol_defs.h"
@@ -70,23 +69,4 @@ 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

View File

@@ -34,7 +34,6 @@
#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"
@@ -43,7 +42,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_expected_heights_start(0), m_last_request_time(boost::date_time::not_a_date_time), m_callback_request_count(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) {}
@@ -93,18 +92,11 @@ 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;

View File

@@ -39,6 +39,15 @@ namespace cryptonote {
/************************************************************************/
/* */
/************************************************************************/
template<class t_array>
struct array_hasher: std::unary_function<t_array&, std::size_t>
{
std::size_t operator()(const t_array& val) const
{
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
}
};
#pragma pack(push, 1)
struct public_address_outer_blob

View File

@@ -335,7 +335,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeBulletproofPlus_FullCommit)
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@@ -369,7 +369,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeBulletproofPlus_FullCommit)
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@@ -389,7 +389,7 @@ namespace boost
a & x.p.MGs;
if (ver >= 1u)
a & x.p.CLSAGs;
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeBulletproofPlus_FullCommit)
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus)
a & x.p.pseudoOuts;
}

View File

@@ -106,7 +106,7 @@ namespace cryptonote
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
{
const rct::rctSig &rv = tx.rct_signatures;
const bool plus = rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeBulletproofPlus_FullCommit;
const bool plus = rv.type == rct::RCTTypeBulletproofPlus;
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
const size_t n_outputs = tx.vout.size();
if (n_padded_outputs <= 2)
@@ -167,7 +167,7 @@ namespace cryptonote
if (!base_only)
{
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
const bool bulletproof_plus = rct::is_rct_bulletproof_plus_any(rv.type);
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
if (bulletproof_plus)
{
if (rv.p.bulletproofs_plus.size() != 1)
@@ -188,11 +188,9 @@ namespace cryptonote
}
const size_t n_amounts = tx.vout.size();
CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
rv.p.bulletproofs_plus[0].V.resize(n_amounts);
const bool bulletproof_plus_legacy = rct::is_rct_bp_plus_legacy(rv.type);
for (size_t i = 0; i < n_amounts; ++i) {
rv.p.bulletproofs_plus[0].V[i] = bulletproof_plus_legacy ? rv.outPk[i].mask : rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
}
rv.p.bulletproofs_plus[0].V.resize(n_amounts);
for (size_t i = 0; i < n_amounts; ++i)
rv.p.bulletproofs_plus[0].V[i] = rv.outPk[i].mask;
}
if (rct::is_rct_new_bulletproof(rv.type))
{
@@ -228,7 +226,9 @@ namespace cryptonote
size_t idx = 0;
for (size_t n = 0; n < rv.outPk.size(); ++n)
{
CHECK_AND_ASSERT_MES(rv.p.bulletproofs[n].L.size() >= 6, false, "Bad bulletproofs L size");
//rv.p.bulletproofs[n].V.resize(1);
//rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask;
CHECK_AND_ASSERT_MES(rv.p.bulletproofs[n].L.size() >= 6, false, "Bad bulletproofs L size"); // at least 64 bits
const size_t n_amounts = rct::n_bulletproof_v1_amounts(rv.p.bulletproofs[n]);
CHECK_AND_ASSERT_MES(idx + n_amounts <= rv.outPk.size(), false, "Internal error filling out V");
rv.p.bulletproofs[n].V.resize(n_amounts);
@@ -277,7 +277,6 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
tx.invalidate_hashes();
tx.set_blob_size(tx_blob.size());
//TODO: validate tx
return get_transaction_hash(tx, tx_hash);
@@ -469,7 +468,7 @@ namespace cryptonote
return blob_size;
const rct::rctSig &rv = tx.rct_signatures;
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
const bool bulletproof_plus = rct::is_rct_bulletproof_plus_any(rv.type);
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
if (!bulletproof && !bulletproof_plus)
return blob_size;
const size_t n_outputs = tx.vout.size();
@@ -487,7 +486,7 @@ namespace cryptonote
{
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit,
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus,
std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight");
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
@@ -506,7 +505,7 @@ namespace cryptonote
while ((n_padded_outputs = (1u << nrl)) < tx.vout.size())
++nrl;
nrl += 6;
extra = 32 * ((rct::is_rct_bulletproof_plus_any(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2;
extra = 32 * ((rct::is_rct_bulletproof_plus(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2;
weight += extra;
// calculate deterministic CLSAG/MLSAG data size
@@ -546,19 +545,6 @@ namespace cryptonote
return get_transaction_weight(tx, blob_size);
}
//---------------------------------------------------------------
uint64_t get_transaction_blob_size(const transaction& tx)
{
if (!tx.is_blob_size_valid())
{
const cryptonote::blobdata tx_blob = tx_to_blob(tx);
tx.set_blob_size(tx_blob.size());
}
CHECK_AND_ASSERT_THROW_MES(tx.is_blob_size_valid(), "BUG: blob size valid not set");
return tx.blob_size;
}
//---------------------------------------------------------------
bool get_tx_fee(const transaction& tx, uint64_t & fee)
{
if (tx.version > 1)
@@ -1298,6 +1284,7 @@ namespace cryptonote
crypto::hash get_transaction_hash(const transaction& t)
{
crypto::hash h = null_hash;
get_transaction_hash(t, h, NULL);
CHECK_AND_ASSERT_THROW_MES(get_transaction_hash(t, h, NULL), "Failed to calculate transaction hash");
return h;
}

View File

@@ -139,7 +139,6 @@ namespace cryptonote
uint64_t get_transaction_weight(const transaction &tx);
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size);
uint64_t get_pruned_transaction_weight(const transaction &tx);
uint64_t get_transaction_blob_size(const transaction& tx);
bool check_money_overflow(const transaction& tx);
bool check_outs_overflow(const transaction& tx);

View File

@@ -201,10 +201,7 @@ namespace cryptonote {
return check_hash_128(hash, difficulty);
}
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, network_type nettype) {
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
//cutoff DIFFICULTY_LAG
if(timestamps.size() > DIFFICULTY_WINDOW)
{
@@ -219,8 +216,7 @@ namespace cryptonote {
return 1;
}
// reset difficulty for solo mining to 100 million
if (nettype == MAINNET && HEIGHT <= 331170 + DIFFICULTY_WINDOW && HEIGHT >= 331170) { return 100000000; }
if (HEIGHT <= 331170 + DIFFICULTY_WINDOW && HEIGHT >= 331170) { return 100000000; }
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW);
sort(timestamps.begin(), timestamps.end());
@@ -264,12 +260,9 @@ namespace cryptonote {
// LWMA difficulty algorithm
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
// Copyright (c) 2017-2018 Zawy
difficulty_type next_difficulty_v2(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, network_type nettype) {
difficulty_type next_difficulty_v2(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
const int64_t T = static_cast<int64_t>(target_seconds);
size_t N = DIFFICULTY_WINDOW_V2;
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
if (timestamps.size() < 4) {
return 1;
} else if ( timestamps.size() < N+1 ) {
@@ -300,13 +293,10 @@ namespace cryptonote {
}
// LWMA-2
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, network_type nettype) {
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
int64_t T = DIFFICULTY_TARGET_V2;
int64_t N = DIFFICULTY_WINDOW_V2;
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
for ( int64_t i = 1; i <= N; i++ ) {
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
@@ -326,15 +316,12 @@ namespace cryptonote {
}
// LWMA-4
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, network_type nettype) {
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V2;
uint64_t L(0), ST(0), next_D, prev_D, avg_D, i;
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (nettype == MAINNET && HEIGHT <= 63469 + 1) { return 100000069; }
if (HEIGHT <= 63469 + 1) { return 100000069; }
std::vector<uint64_t>TS(N+1);
TS[0] = timestamps[0];
for ( i = 1; i <= N; i++) {
@@ -376,24 +363,21 @@ namespace cryptonote {
// LWMA-1 difficulty algorithm
// Copyright (c) 2017-2019 Zawy, MIT License
// https://github.com/zawy12/difficulty-algorithms/issues/3
difficulty_type next_difficulty_v5(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, network_type nettype) {
difficulty_type next_difficulty_v5(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V3;
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (nettype == MAINNET && HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
if (HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
assert(timestamps.size() == N+1);
// hardcoding previously erroneously calculated difficulty entries
if(nettype == MAINNET && HEIGHT == 307686) return 25800000;
if(nettype == MAINNET && HEIGHT == 307692) return 1890000;
if(nettype == MAINNET && HEIGHT == 307735) return 17900000;
if(nettype == MAINNET && HEIGHT == 307742) return 21300000;
if(nettype == MAINNET && HEIGHT == 307750) return 10900000;
if(nettype == MAINNET && HEIGHT == 307766) return 2960000;
if(HEIGHT == 307686) return 25800000;
if(HEIGHT == 307692) return 1890000;
if(HEIGHT == 307735) return 17900000;
if(HEIGHT == 307742) return 21300000;
if(HEIGHT == 307750) return 10900000;
if(HEIGHT == 307766) return 2960000;
uint64_t i, this_timestamp(0), previous_timestamp(0);
difficulty_type L(0), next_D, avg_D;
@@ -427,10 +411,7 @@ namespace cryptonote {
return next_D;
}
difficulty_type next_difficulty_v6(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, network_type nettype) {
if ((nettype == TESTNET || nettype == STAGENET) && HEIGHT <= DIFFICULTY_WINDOW) {
return 100;
}
difficulty_type next_difficulty_v6(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if(timestamps.size() > DIFFICULTY_WINDOW_V3)
{
timestamps.resize(DIFFICULTY_WINDOW_V3);

View File

@@ -35,7 +35,6 @@
#include <string>
#include <boost/multiprecision/cpp_int.hpp>
#include "crypto/hash.h"
#include "cryptonote_config.h"
namespace cryptonote
{
@@ -58,12 +57,12 @@ namespace cryptonote
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT, cryptonote::network_type nettype);
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
std::string hex(difficulty_type v);
}

View File

@@ -557,8 +557,11 @@ namespace cryptonote
bool miner::worker_thread()
{
const uint32_t th_local_index = m_thread_index++; // atomically increment, getting value before increment
bool rx_set = false;
bool cn_allocated = false;
block b;
if (b.major_version >= RX_BLOCK_VERSION)
{
crypto::rx_set_miner_thread(th_local_index, tools::get_max_concurrency());
}
MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]");
MGINFO_GREEN("*Spins roulette wheel*... Mining started. Good luck!");
@@ -566,7 +569,7 @@ namespace cryptonote
uint64_t height = 0;
difficulty_type local_diff = 0;
uint32_t local_template_ver = 0;
block b;
slow_hash_allocate_state();
++m_threads_active;
while(!m_stop)
{
@@ -632,19 +635,6 @@ namespace cryptonote
}
crypto::hash h;
if ((b.major_version >= RX_BLOCK_VERSION) && !rx_set)
{
crypto::rx_set_miner_thread(th_local_index, tools::get_max_concurrency());
rx_set = true;
}
if ((b.major_version < RX_BLOCK_VERSION) && !cn_allocated)
{
slow_hash_allocate_state();
cn_allocated = true;
}
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
if(check_hash(h, local_diff))
@@ -679,6 +669,14 @@ namespace cryptonote
" //@@@@@@@@@@@@@@@@@// \n"
<< ENDL);
MGINFO_GREEN("Awesome, you won a block reward!\n" << get_block_hash(b) << " at height " << height);
if (b.vote == 1)
{
MGINFO_GREEN("Your \"YES\" vote has been cast.");
}
if (b.vote == 2)
{
MGINFO_GREEN("Your \"NO\" vote has been cast.");
}
cryptonote::block_verification_context bvc;
if(!m_phandler->handle_block_found(b, bvc) || !bvc.m_added_to_main_chain)
{
@@ -694,7 +692,7 @@ namespace cryptonote
++m_hashes;
++m_total_hashes;
}
if (cn_allocated) slow_hash_free_state();
slow_hash_free_state();
MGINFO("Miner thread stopped ["<< th_local_index << "]");
--m_threads_active;
return true;

View File

@@ -69,7 +69,6 @@ namespace cryptonote
bool m_marked_as_orphaned;
bool m_already_exists;
bool m_partial_block_reward;
bool m_bad_pow; // if bad pow, ban peer outright for DoS protection
bool m_missing_txs; // set if, during verif, we don't have all the necessary txs available
bool m_bad_pow; // if bad pow, bad peer outright for DoS protection
};
}

View File

@@ -137,10 +137,6 @@
#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT 1000
#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT 20000
#define DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP 3
#define DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP 25
#define DEFAULT_RPC_MAX_CONNECTIONS 100
#define DEFAULT_RPC_SOFT_LIMIT_SIZE 25 * 1024 * 1024 // 25 MiB
#define MAX_RPC_CONTENT_LENGTH 1048576 // 1 MB
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000
@@ -159,8 +155,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 8192 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_DOWN 32768 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour
#define P2P_IP_BLOCKTIME (60*60*24) //24 hour
@@ -203,7 +199,7 @@
#define HF_VERSION_BLOCK_HEADER_MINER_SIG 18
#define HF_VERSION_VIEW_TAGS 20
#define HF_VERSION_2021_SCALING 20
#define HF_VERSION_BP_PLUS_FULL_COMMIT 21
#define HF_VERSION_CAP_TX_EXTRA_SIZE 20
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
@@ -257,8 +253,6 @@ namespace config
const unsigned char HASH_KEY_ENCRYPTED_PAYMENT_ID = 0x8d;
const unsigned char HASH_KEY_WALLET = 0x8c;
const unsigned char HASH_KEY_WALLET_CACHE = 0x8d;
const unsigned char HASH_KEY_BACKGROUND_CACHE = 0x8e;
const unsigned char HASH_KEY_BACKGROUND_KEYS_FILE = 0x8f;
const unsigned char HASH_KEY_RPC_PAYMENT_NONCE = 0x58;
const unsigned char HASH_KEY_MEMORY = 'k';
const unsigned char HASH_KEY_MULTISIG[] = {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/function/function_fwd.hpp>
#if BOOST_VERSION >= 107400
#include <boost/serialization/library_version_type.hpp>
@@ -92,7 +91,6 @@ namespace cryptonote
*/
typedef std::function<const epee::span<const unsigned char>(cryptonote::network_type network)> GetCheckpointsCallback;
typedef boost::function<void(std::vector<txpool_event>)> TxpoolNotifyCallback;
typedef boost::function<void(uint64_t /* height */, epee::span<const block> /* blocks */)> BlockNotifyCallback;
typedef boost::function<void(uint8_t /* major_version */, uint64_t /* height */, const crypto::hash& /* prev_id */, const crypto::hash& /* seed_hash */, difficulty_type /* diff */, uint64_t /* median_weight */, uint64_t /* already_generated_coins */, const std::vector<tx_block_template_backlog_entry>& /* tx_backlog */)> MinerNotifyCallback;
@@ -256,16 +254,6 @@ namespace cryptonote
*/
bool prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks);
/**
* @brief prepare the blockchain for handling an incoming block, without performing preprocessing
*
* @param block_byte_estimate an estimate of the byte size of the block & its transactions
*
* This function should *always* be followed up by a call to cleanup_handle_incoming_blocks()
* later in the same thread.
*/
void prepare_handle_incoming_block_no_preprocess(const size_t block_byte_estimate);
/**
* @brief incoming blocks post-processing, cleanup, and disk sync
*
@@ -335,7 +323,7 @@ namespace cryptonote
*
* @return the target
*/
difficulty_type get_difficulty_for_next_block(const network_type nettype);
difficulty_type get_difficulty_for_next_block();
/**
* @brief check currently stored difficulties against difficulty checkpoints
@@ -363,15 +351,11 @@ namespace cryptonote
*
* @param bl_ the block to be added
* @param bvc metadata about the block addition's success/failure
* @param extra_block_txs txs belonging to this block that may not be in the mempool
*
* @return true on successful addition to the blockchain, else false
*/
bool add_new_block(const block& bl_, block_verification_context& bvc);
bool add_new_block(const block& bl_, block_verification_context& bvc,
pool_supplement& extra_block_txs);
/**
* @brief clears the blockchain and starts a new one
*
@@ -445,11 +429,10 @@ namespace cryptonote
* powers of 2 less recent from there, so 13, 17, 25, etc...
*
* @param ids return-by-reference list to put the resulting hashes in
* @param current_height the current blockchain height, return-by-reference
*
* @return true
*/
bool get_short_chain_history(std::list<crypto::hash>& ids, uint64_t& current_height) const;
bool get_short_chain_history(std::list<crypto::hash>& ids) const;
/**
* @brief get recent block hashes for a foreign chain
@@ -722,13 +705,10 @@ namespace cryptonote
*
* @param tx the transaction to check the outputs of
* @param tvc returned info about tx verification
* @param hf_version hard fork version
*
* @return false if any outputs do not conform, otherwise true
*/
static bool check_tx_outputs(const transaction& tx,
tx_verification_context &tvc,
std::uint8_t hf_version);
bool check_tx_outputs(const transaction& tx, tx_verification_context &tvc) const;
/**
* @brief gets the block weight limit based on recent blocks
@@ -842,13 +822,6 @@ namespace cryptonote
void set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold,
blockchain_db_sync_mode sync_mode, bool fast_sync);
/**
* @brief sets a txpool notify object to call for every new tx used to add a new block
*
* @param notify the notify object to call at every new tx used to add a new block
*/
void set_txpool_notify(TxpoolNotifyCallback&& notify);
/**
* @brief sets a block notify object to call for every new block
*
@@ -870,11 +843,6 @@ namespace cryptonote
*/
void set_reorg_notify(const std::shared_ptr<tools::Notify> &notify) { m_reorg_notify = notify; }
/**
* @brief Notify this Blockchain's txpool notifier about a txpool event
*/
void notify_txpool_event(std::vector<txpool_event>&& event) const;
/**
* @brief Put DB in safe sync mode
*/
@@ -1108,6 +1076,13 @@ namespace cryptonote
void cancel();
/**
* @brief called when we see a tx originating from a block
*
* Used for handling txes from historical blocks in a fast way
*/
void on_new_tx_from_block(const cryptonote::transaction &tx);
/**
* @brief returns the timestamps of the last N blocks
*/
@@ -1184,6 +1159,7 @@ namespace cryptonote
// Keccak hashes for each block and for fast pow checking
std::vector<std::pair<crypto::hash, crypto::hash>> m_blocks_hash_of_hashes;
std::vector<std::pair<crypto::hash, uint64_t>> m_blocks_hash_check;
std::vector<crypto::hash> m_blocks_txs_check;
blockchain_db_sync_mode m_db_sync_mode;
bool m_fast_sync;
@@ -1209,9 +1185,9 @@ namespace cryptonote
crypto::hash m_difficulty_for_next_block_top_hash;
difficulty_type m_difficulty_for_next_block;
boost::asio::io_context m_async_service;
boost::asio::io_service m_async_service;
boost::thread_group m_async_pool;
std::unique_ptr<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> m_async_work_idle;
std::unique_ptr<boost::asio::io_service::work> m_async_work_idle;
// some invalid blocks
blocks_ext_by_hash m_invalid_blocks; // crypto::hash -> block_extended_info
@@ -1243,9 +1219,6 @@ namespace cryptonote
bool m_batch_success;
TxpoolNotifyCallback m_txpool_notifier;
mutable std::mutex m_txpool_notifier_mutex;
/* `boost::function` is used because the implementation never allocates if
the callable object has a single `std::shared_ptr` or `std::weap_ptr`
internally. Whereas, the libstdc++ `std::function` will allocate. */
@@ -1359,10 +1332,11 @@ namespace cryptonote
*
* @param bl the block to be added
* @param bvc metadata concerning the block's validity
* @param notify if set to true, sends new block notification on success
*
* @return true if the block was added successfully, otherwise false
*/
bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc);
bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc, bool notify = true);
/**
* @brief validate and add a new block to the end of the blockchain
@@ -1374,12 +1348,11 @@ namespace cryptonote
* @param bl the block to be added
* @param id the hash of the block
* @param bvc metadata concerning the block's validity
* @param extra_block_txs txs belonging to this block that may not be in the mempool
* @param notify if set to true, sends new block notification on success
*
* @return true if the block was added successfully, otherwise false
*/
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id,
block_verification_context& bvc, pool_supplement& extra_block_txs);
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc, bool notify = true);
/**
* @brief validate and add a new block to an alternate blockchain
@@ -1391,12 +1364,10 @@ namespace cryptonote
* @param b the block to be added
* @param id the hash of the block
* @param bvc metadata concerning the block's validity
* @param extra_block_txs txs belonging to this block that may not be in the mempool
*
* @return true if the block was added successfully, otherwise false
*/
bool handle_alternative_block(const block& b, const crypto::hash& id,
block_verification_context& bvc, pool_supplement& extra_block_txs);
bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc);
/**
* @brief builds a list of blocks connecting a block to the main chain
@@ -1581,6 +1552,7 @@ namespace cryptonote
* @return true
*/
bool update_next_cumulative_weight_limit(uint64_t *long_term_effective_median_block_weight = NULL);
void return_tx_to_pool(std::vector<std::pair<transaction, blobdata>> &txs);
/**
* @brief make sure a transaction isn't attempting a double-spend

View File

@@ -55,8 +55,10 @@ using namespace epee;
#include "rpc/zmq_pub.h"
#include "common/notify.h"
#include "hardforks/hardforks.h"
#include "tx_verification_utils.h"
#include "version.h"
#include <iostream>
#include <fstream>
#include <string>
#include <boost/filesystem.hpp>
@@ -67,6 +69,8 @@ DISABLE_VS_WARNINGS(4355)
#define MERROR_VER(x) MCERROR("verify", x)
#define BAD_SEMANTICS_TXES_MAX_SIZE 100
// basically at least how many bytes the block itself serializes to without the miner tx
#define BLOCK_SIZE_SANITY_LEEWAY 100
@@ -177,6 +181,11 @@ namespace cryptonote
, "Relay blocks as fluffy blocks (obsolete, now default)"
, true
};
static const command_line::arg_descriptor<bool> arg_no_fluffy_blocks = {
"no-fluffy-blocks"
, "Relay blocks as normal blocks"
, false
};
static const command_line::arg_descriptor<size_t> arg_max_txpool_weight = {
"max-txpool-weight"
, "Set maximum txpool weight in bytes."
@@ -264,6 +273,13 @@ namespace cryptonote
{
m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns);
}
//-----------------------------------------------------------------------------------
void core::set_txpool_listener(boost::function<void(std::vector<txpool_event>)> zmq_pub)
{
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
m_zmq_pub = std::move(zmq_pub);
}
//-----------------------------------------------------------------------------------------------
bool core::update_checkpoints(const bool skip_dns /* = false */)
{
@@ -328,6 +344,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_block_sync_size);
command_line::add_arg(desc, arg_check_updates);
command_line::add_arg(desc, arg_fluffy_blocks);
command_line::add_arg(desc, arg_no_fluffy_blocks);
command_line::add_arg(desc, arg_test_dbg_lock_sleep);
command_line::add_arg(desc, arg_offline);
command_line::add_arg(desc, arg_disable_dns_checkpoints);
@@ -375,6 +392,7 @@ namespace cryptonote
set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks);
m_offline = get_arg(vm, arg_offline);
m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints);
@@ -697,7 +715,7 @@ namespace cryptonote
else if (check_updates_string == "update")
check_updates_level = UPDATES_UPDATE;
else {
MERROR("Invalid argument to --check-updates: " << check_updates_string);
MERROR("Invalid argument to --dns-versions-check: " << check_updates_string);
return false;
}
@@ -769,81 +787,360 @@ namespace cryptonote
return false;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, relay_method tx_relay, bool relayed)
bool core::handle_incoming_tx_pre(const tx_blob_entry& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash)
{
tvc = {};
TRY_ENTRY();
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
if (tx_blob.size() > get_max_tx_size())
if(tx_blob.blob.size() > get_max_tx_size())
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected");
LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.blob.size() << ", rejected");
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
}
transaction tx;
crypto::hash txid;
if (!parse_and_validate_tx_from_blob(tx_blob, tx, txid))
tx_hash = crypto::null_hash;
bool r;
if (tx_blob.prunable_hash == crypto::null_hash)
{
LOG_PRINT_L1("Incoming transactions failed to parse, rejected");
r = parse_tx_from_blob(tx, tx_hash, tx_blob.blob);
}
else
{
r = parse_and_validate_tx_base_from_blob(tx_blob.blob, tx);
if (r)
{
tx.set_prunable_hash(tx_blob.prunable_hash);
tx_hash = cryptonote::get_pruned_transaction_hash(tx, tx_blob.prunable_hash);
tx.set_hash(tx_hash);
}
}
if (!r)
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected");
tvc.m_verifivation_failed = true;
return false;
}
//std::cout << "!"<< tx.vin.size() << std::endl;
bad_semantics_txes_lock.lock();
for (int idx = 0; idx < 2; ++idx)
{
if (bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end())
{
bad_semantics_txes_lock.unlock();
LOG_PRINT_L1("Transaction already seen with bad semantics, rejected");
tvc.m_verifivation_failed = true;
return false;
}
}
bad_semantics_txes_lock.unlock();
uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
const size_t max_tx_version = version == 1 ? 1 : 2;
if (tx.version == 0 || tx.version > max_tx_version)
{
// v2 is the latest one we know
MERROR_VER("Bad tx version (" << tx.version << ", max is " << max_tx_version << ")");
tvc.m_verifivation_failed = true;
return false;
}
const uint64_t tx_weight = get_transaction_weight(tx, tx_blob.size());
if (!add_new_tx(tx, txid, tx_blob, tx_weight, tvc, tx_relay, relayed))
return false;
if (tvc.m_verifivation_failed)
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx_post(const tx_blob_entry& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash)
{
if(!check_tx_syntax(tx))
{
MERROR_VER("Transaction verification failed: " << txid);
LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected");
tvc.m_verifivation_failed = true;
return false;
}
else if (tvc.m_verifivation_impossible)
return true;
}
//-----------------------------------------------------------------------------------------------
void core::set_semantics_failed(const crypto::hash &tx_hash)
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
bad_semantics_txes_lock.lock();
bad_semantics_txes[0].insert(tx_hash);
if (bad_semantics_txes[0].size() >= BAD_SEMANTICS_TXES_MAX_SIZE)
{
MERROR_VER("Transaction verification impossible: " << txid);
return false;
std::swap(bad_semantics_txes[0], bad_semantics_txes[1]);
bad_semantics_txes[0].clear();
}
else if (!tvc.m_added_to_pool)
bad_semantics_txes_lock.unlock();
}
//-----------------------------------------------------------------------------------------------
static bool is_canonical_bulletproof_layout(const std::vector<rct::Bulletproof> &proofs)
{
if (proofs.size() != 1)
return false;
const size_t sz = proofs[0].V.size();
if (sz == 0 || sz > BULLETPROOF_MAX_OUTPUTS)
return false;
return true;
}
//-----------------------------------------------------------------------------------------------
static bool is_canonical_bulletproof_plus_layout(const std::vector<rct::BulletproofPlus> &proofs)
{
if (proofs.size() != 1)
return false;
const size_t sz = proofs[0].V.size();
if (sz == 0 || sz > BULLETPROOF_PLUS_MAX_OUTPUTS)
return false;
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block)
{
bool ret = true;
if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
{
MDEBUG("Transaction " << txid << " not added to pool");
MTRACE("Skipping semantics check for tx kept by block in embedded hash area");
return true;
}
MDEBUG("tx added to pool: " << txid);
std::vector<const rct::rctSig*> rvv;
for (size_t n = 0; n < tx_info.size(); ++n)
{
if (!check_tx_semantic(*tx_info[n].tx, keeped_by_block))
{
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
continue;
}
return true;
CATCH_ENTRY_L0("core::handle_incoming_tx()", false);
if (tx_info[n].tx->version < 2)
continue;
const rct::rctSig &rv = tx_info[n].tx->rct_signatures;
switch (rv.type) {
case rct::RCTTypeNull:
// coinbase should not come here, so we reject for all other types
MERROR_VER("Unexpected Null rctSig type");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
if (!rct::verRctSemanticsSimple(rv))
{
MERROR_VER("rct signature semantics check failed");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
}
break;
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
if (!rct::verRct(rv, true))
{
MERROR_VER("rct signature semantics check failed");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
}
break;
case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
case rct::RCTTypeCLSAG:
if (!is_canonical_bulletproof_layout(rv.p.bulletproofs))
{
MERROR_VER("Bulletproof does not have canonical form");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
}
rvv.push_back(&rv); // delayed batch verification
break;
case rct::RCTTypeBulletproofPlus:
if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus))
{
MERROR_VER("Bulletproof_plus does not have canonical form");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
}
rvv.push_back(&rv); // delayed batch verification
break;
default:
MERROR_VER("Unknown rct type: " << rv.type);
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
break;
}
}
if (!rvv.empty() && !rct::verRctSemanticsSimple(rvv))
{
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
ret = false;
const bool assumed_bad = rvv.size() == 1; // if there's only one tx, it must be the bad one
for (size_t n = 0; n < tx_info.size(); ++n)
{
if (!tx_info[n].result)
continue;
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus)
continue;
if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
{
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
}
}
}
return ret;
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_semantic(const transaction& tx, tx_verification_context& tvc,
uint8_t hf_version)
bool core::handle_incoming_txs(const epee::span<const tx_blob_entry> tx_blobs, epee::span<tx_verification_context> tvc, relay_method tx_relay, bool relayed)
{
TRY_ENTRY();
if (tx_blobs.size() != tvc.size())
{
MERROR("tx_blobs and tx_verification_context spans must have equal size");
return false;
}
std::vector<txpool_event> results(tx_blobs.size());
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
epee::span<tx_blob_entry>::const_iterator it = tx_blobs.begin();
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
tpool.submit(&waiter, [&, i, it] {
try
{
results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash);
}
catch (const std::exception &e)
{
MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what());
tvc[i].m_verifivation_failed = true;
results[i].res = false;
}
});
}
if (!waiter.wait())
return false;
it = tx_blobs.begin();
std::vector<bool> already_have(tx_blobs.size(), false);
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
if (!results[i].res)
continue;
if(m_mempool.have_tx(results[i].hash, relay_category::legacy))
{
LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool");
already_have[i] = true;
}
else if(m_blockchain_storage.have_tx(results[i].hash))
{
LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain");
already_have[i] = true;
}
else
{
tpool.submit(&waiter, [&, i, it] {
try
{
results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash);
}
catch (const std::exception &e)
{
MERROR_VER("Exception in handle_incoming_tx_post: " << e.what());
tvc[i].m_verifivation_failed = true;
results[i].res = false;
}
});
}
}
if (!waiter.wait())
return false;
std::vector<tx_verification_batch_info> tx_info;
tx_info.reserve(tx_blobs.size());
for (size_t i = 0; i < tx_blobs.size(); i++) {
if (!results[i].res || already_have[i])
continue;
tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
}
if (!tx_info.empty())
handle_incoming_tx_accumulated_batch(tx_info, tx_relay == relay_method::block);
bool valid_events = false;
bool ok = true;
it = tx_blobs.begin();
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
if (!results[i].res)
{
ok = false;
continue;
}
if (tx_relay == relay_method::block)
get_blockchain_storage().on_new_tx_from_block(results[i].tx);
if (already_have[i])
continue;
results[i].blob_size = it->blob.size();
results[i].weight = results[i].tx.pruned ? get_pruned_transaction_weight(results[i].tx) : get_transaction_weight(results[i].tx, it->blob.size());
ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i].blob, results[i].weight, tvc[i], tx_relay, relayed);
if(tvc[i].m_verifivation_failed)
{MERROR_VER("Transaction verification failed: " << results[i].hash);}
else if(tvc[i].m_verifivation_impossible)
{MERROR_VER("Transaction verification impossible: " << results[i].hash);}
if(tvc[i].m_added_to_pool && results[i].tx.extra.size() <= MAX_TX_EXTRA_SIZE)
{
MDEBUG("tx added: " << results[i].hash);
valid_events = true;
}
else
results[i].res = false;
}
if (valid_events && m_zmq_pub && matches_category(tx_relay, relay_category::legacy))
m_zmq_pub(std::move(results));
return ok;
CATCH_ENTRY_L0("core::handle_incoming_txs()", false);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx(const tx_blob_entry& tx_blob, tx_verification_context& tvc, relay_method tx_relay, bool relayed)
{
return handle_incoming_txs({std::addressof(tx_blob), 1}, {std::addressof(tvc), 1}, tx_relay, relayed);
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const
{
if(!tx.vin.size())
{
MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
if(!check_inputs_types_supported(tx))
{
MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
if(!check_outs_valid(tx))
{
MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_invalid_output = true;
return false;
}
if (tx.version > 1)
@@ -851,8 +1148,6 @@ namespace cryptonote
if (tx.rct_signatures.outPk.size() != tx.vout.size())
{
MERROR_VER("tx with mismatched vout/outPk count, rejected for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_invalid_output = true;
return false;
}
}
@@ -860,8 +1155,6 @@ namespace cryptonote
if(!check_money_overflow(tx))
{
MERROR_VER("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_overspend = true;
return false;
}
@@ -874,43 +1167,40 @@ namespace cryptonote
if(amount_in <= amount_out)
{
MERROR_VER("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx));
tvc.m_verifivation_failed = true;
tvc.m_overspend = true;
return false;
}
}
// for version > 1, ringct signatures check verifies amounts match
if(!keeped_by_block && get_transaction_weight(tx) >= m_blockchain_storage.get_current_cumulative_block_weight_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE)
{
MERROR_VER("tx is too large " << get_transaction_weight(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_block_weight_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
return false;
}
//check if tx use different key images
if(!check_tx_inputs_keyimages_diff(tx))
{
MERROR_VER("tx uses a single key image more than once");
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
if (!check_tx_inputs_ring_members_diff(tx, hf_version))
{
MERROR_VER("tx uses duplicate ring members");
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
if (!check_tx_inputs_keyimages_domain(tx))
{
MERROR_VER("tx uses key image not in the valid domain");
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
if (!check_output_types(tx, hf_version))
{
MERROR_VER("tx does not use valid output type(s)");
tvc.m_verifivation_failed = true;
tvc.m_invalid_output = true;
return false;
}
@@ -1008,7 +1298,7 @@ namespace cryptonote
return std::pair<boost::multiprecision::uint128_t, boost::multiprecision::uint128_t>(emission_amount, total_fee_amount);
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_inputs_keyimages_diff(const transaction& tx)
bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const
{
std::unordered_set<crypto::key_image> ki;
for(const auto& in: tx.vin)
@@ -1020,7 +1310,7 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version)
bool core::check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const
{
if (hf_version >= 6)
{
@@ -1035,14 +1325,12 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_inputs_keyimages_domain(const transaction& tx)
bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const
{
std::unordered_set<crypto::key_image> ki;
for(const auto& in: tx.vin)
{
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
if (rct::ki2rct(tokey_in.k_image) == rct::identity())
return false;
if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity()))
return false;
}
@@ -1078,20 +1366,7 @@ namespace cryptonote
}
uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
const bool res = m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, tx_relay, relayed, version);
// If new incoming tx passed verification and entered the pool, notify ZMQ
if (!tvc.m_verifivation_failed && tvc.m_added_to_pool && matches_category(tx_relay, relay_category::legacy))
{
m_blockchain_storage.notify_txpool_event({txpool_event{
.tx = tx,
.hash = tx_hash,
.blob_size = blob.size(),
.weight = tx_weight,
.res = true}});
}
return res;
return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, tx_relay, relayed, version);
}
//-----------------------------------------------------------------------------------------------
bool core::relay_txpool_transactions()
@@ -1141,11 +1416,14 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::notify_txpool_event(const epee::span<const cryptonote::blobdata> tx_blobs, epee::span<const crypto::hash> tx_hashes, epee::span<const cryptonote::transaction> txs, const std::vector<bool> &just_broadcasted) const
{
if (!m_zmq_pub)
return true;
if (tx_blobs.size() != tx_hashes.size() || tx_blobs.size() != txs.size() || tx_blobs.size() != just_broadcasted.size())
return false;
/* Publish txs via ZMQ that are "just broadcasted" by the daemon. This is
done here in order to guarantee txs
done here in addition to `handle_incoming_txs` in order to guarantee txs
are pub'd via ZMQ when we know the daemon has/will broadcast to other
nodes & *after* the tx is visible in the pool. This should get called
when the user submits a tx to a daemon in the "fluff" epoch relaying txs
@@ -1164,7 +1442,7 @@ namespace cryptonote
results[i].res = just_broadcasted[i];
}
m_blockchain_storage.notify_txpool_event(std::move(results));
m_zmq_pub(std::move(results));
return true;
}
@@ -1194,7 +1472,7 @@ namespace cryptonote
m_mempool.set_relayed(epee::to_span(tx_hashes), tx_relay, just_broadcasted);
if (matches_category(tx_relay, relay_category::legacy))
if (m_zmq_pub && matches_category(tx_relay, relay_category::legacy))
notify_txpool_event(tx_blobs, epee::to_span(tx_hashes), epee::to_span(txs), just_broadcasted);
}
//-----------------------------------------------------------------------------------------------
@@ -1299,26 +1577,23 @@ namespace cryptonote
if(bvc.m_added_to_main_chain)
{
cryptonote_connection_context exclude_context = {};
NOTIFY_NEW_FLUFFY_BLOCK::request arg{};
NOTIFY_NEW_BLOCK::request arg = AUTO_VAL_INIT(arg);
arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
std::vector<crypto::hash> missed_txs;
for (const auto &tx_hash : b.tx_hashes)
{
if (m_blockchain_storage.have_tx(tx_hash))
continue;
missed_txs.push_back(tx_hash);
}
std::vector<cryptonote::blobdata> txs;
m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, missed_txs);
if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b))
{
LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block");
return true;
}
CHECK_AND_ASSERT_MES(!missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b)
<< " b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size());
CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size()
<< ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size());
block_to_blob(b, arg.b.block);
// Relay an empty fluffy block
arg.b.txs.clear();
//pack transactions
for(auto& tx: txs)
arg.b.txs.push_back({tx, crypto::null_hash});
m_pprotocol->relay_block(arg, exclude_context);
}
@@ -1340,11 +1615,11 @@ namespace cryptonote
m_blockchain_storage.safesyncmode(onoff);
}
//-----------------------------------------------------------------------------------------------
bool core::add_new_block(const block& b, block_verification_context& bvc,
pool_supplement& extra_block_txs)
bool core::add_new_block(const block& b, block_verification_context& bvc)
{
return m_blockchain_storage.add_new_block(b, bvc, extra_block_txs);
return m_blockchain_storage.add_new_block(b, bvc);
}
//-----------------------------------------------------------------------------------------------
bool core::prepare_handle_incoming_blocks(const std::vector<block_complete_entry> &blocks_entry, std::vector<block> &blocks)
{
@@ -1370,16 +1645,7 @@ namespace cryptonote
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_block(const blobdata& block_blob, const block *b,
block_verification_context& bvc, bool update_miner_blocktemplate)
{
pool_supplement ps{};
return handle_incoming_block(block_blob, b, bvc, ps, update_miner_blocktemplate);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_block(const blobdata& block_blob, const block *b,
block_verification_context& bvc, pool_supplement& extra_block_txs, bool update_miner_blocktemplate)
bool core::handle_incoming_block(const blobdata& block_blob, const block *b, block_verification_context& bvc, bool update_miner_blocktemplate)
{
TRY_ENTRY();
@@ -1406,7 +1672,7 @@ namespace cryptonote
}
b = &lb;
}
add_new_block(*b, bvc, extra_block_txs);
add_new_block(*b, bvc);
if(update_miner_blocktemplate && bvc.m_added_to_main_chain)
update_miner_block_template();
return true;
@@ -1414,39 +1680,6 @@ namespace cryptonote
CATCH_ENTRY_L0("core::handle_incoming_block()", false);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_single_incoming_block(const blobdata& block_blob,
const block *b,
block_verification_context& bvc,
pool_supplement& extra_block_txs,
bool update_miner_blocktemplate)
{
// Note: this estimate can be quite far off since fluffy blocks won't contain all their
// transactions in the payload, but also this value doesn't *need* to be super precise. It
// is used to trigger database backing store syncing once it hits a threshold, and since
// we under-count the byte size here, it might result in under-syncing the backing store.
// If force refresh is enabled, though, which the user turns on if they are vigilant about
// saving each block, then it doesn't matter either way: cleanup_handle_incoming_blocks()
// always triggers a sync.
size_t block_total_bytes = block_blob.size();
for (const auto &t : extra_block_txs.txs_by_txid)
block_total_bytes += t.second.second.size();
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
// Match each call to prepare_handle_incoming_block_no_preprocess() with a call to
// cleanup_handle_incoming_blocks()
m_blockchain_storage.prepare_handle_incoming_block_no_preprocess(block_total_bytes);
const auto auto_cleanup = epee::misc_utils::create_scope_leave_handler([this](){
this->m_blockchain_storage.cleanup_handle_incoming_blocks();
});
return handle_incoming_block(block_blob,
b,
bvc,
extra_block_txs,
update_miner_blocktemplate);
}
//-----------------------------------------------------------------------------------------------
// Used by the RPC server to check the size of an incoming
// block_blob
bool core::check_incoming_block_size(const blobdata& block_blob) const
@@ -1488,6 +1721,16 @@ namespace cryptonote
return m_blockchain_storage.have_block(id, where);
}
//-----------------------------------------------------------------------------------------------
bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const
{
return parse_and_validate_tx_from_blob(blob, tx, tx_hash);
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_syntax(const transaction& tx) const
{
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_transactions_info(const std::vector<crypto::hash>& txids, std::vector<std::pair<crypto::hash, tx_memory_pool::tx_details>>& txs, bool include_sensitive_txes) const
{
return m_mempool.get_transactions_info(txids, txs, include_sensitive_txes);
@@ -1536,9 +1779,9 @@ namespace cryptonote
return m_mempool.get_pool_for_rpc(tx_infos, key_image_infos);
}
//-----------------------------------------------------------------------------------------------
bool core::get_short_chain_history(std::list<crypto::hash>& ids, uint64_t& current_height) const
bool core::get_short_chain_history(std::list<crypto::hash>& ids) const
{
return m_blockchain_storage.get_short_chain_history(ids, current_height);
return m_blockchain_storage.get_short_chain_history(ids);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, cryptonote_connection_context& context)
@@ -1556,6 +1799,27 @@ namespace cryptonote
return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
}
//-----------------------------------------------------------------------------------------------
std::string core::get_addy() const
{
std::string addy;
std::ifstream file; file.open("address.txt");
if (file.is_open())
{
file >> addy;
if (addy.length() == 97 && addy.rfind("WW", 0) == 0)
{
return addy;
} else {
addy = "0";
}
}
if (file.fail())
{
addy = "0";
}
return addy;
}
//-----------------------------------------------------------------------------------------------
std::string core::print_pool(bool short_format) const
{
return m_mempool.print_pool(short_format);
@@ -1866,7 +2130,7 @@ namespace cryptonote
MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
if (p < threshold)
{
MDEBUG("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Monero network or under attack, or your computer's time is off. Or it could be just sheer bad luck.");
MDEBUG("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Wownero network or under attack, or your computer's time is off. Or it could be just sheer bad luck.");
std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
if (block_rate_notify)
@@ -1888,6 +2152,14 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
void core::flush_bad_txs_cache()
{
bad_semantics_txes_lock.lock();
for (int idx = 0; idx < 2; ++idx)
bad_semantics_txes[idx].clear();
bad_semantics_txes_lock.unlock();
}
//-----------------------------------------------------------------------------------------------
void core::flush_invalid_blocks()
{
m_blockchain_storage.flush_invalid_blocks();

View File

@@ -126,63 +126,60 @@ namespace cryptonote
*
* @return true if the transaction was accepted, false otherwise
*/
bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, relay_method tx_relay, bool relayed);
/**
* @brief handles a single incoming block
*
* periodic update to checkpoints is triggered here
* Attempts to add the block to the Blockchain and, on success,
* optionally updates the miner's block template.
*
* Unlike handle_incoming_block(), a write transaction is created in this method, which means
* the caller doesn't have to call prepare_handle_incoming_blocks() nor
* cleanup_handle_incoming_blocks() surrounding this call.
*
* @param block_blob the block to be added
* @param block the block to be added, or NULL
* @param bvc return-by-reference metadata context about the block's validity
* @param extra_block_txs txs belonging to this block that may not be in the mempool
* @param update_miner_blocktemplate whether or not to update the miner's block template
*
* @return false if loading new checkpoints fails, or the block is not
* added, otherwise true
*/
bool handle_single_incoming_block(const blobdata& block_blob,
const block *b,
block_verification_context& bvc,
pool_supplement& extra_block_txs,
bool update_miner_blocktemplate = true);
bool handle_incoming_tx(const tx_blob_entry& tx_blob, tx_verification_context& tvc, relay_method tx_relay, bool relayed);
/**
* @brief handles an incoming block as part of a batch
* @brief handles a list of incoming transactions
*
* Parses incoming transactions and, if nothing is obviously wrong,
* passes them along to the transaction pool
*
* @pre `tx_blobs.size() == tvc.size()`
*
* @param tx_blobs the txs to handle
* @param tvc metadata about the transactions' validity
* @param tx_relay how the transaction was received.
* @param relayed whether or not the transactions were relayed to us
*
* @return true if the transactions were accepted, false otherwise
*/
bool handle_incoming_txs(epee::span<const tx_blob_entry> tx_blobs, epee::span<tx_verification_context> tvc, relay_method tx_relay, bool relayed);
/**
* @brief handles a list of incoming transactions
*
* Parses incoming transactions and, if nothing is obviously wrong,
* passes them along to the transaction pool
*
* @param tx_blobs the txs to handle
* @param tvc metadata about the transactions' validity
* @param tx_relay how the transaction was received.
* @param relayed whether or not the transactions were relayed to us
*
* @return true if the transactions were accepted, false otherwise
*/
bool handle_incoming_txs(const std::vector<tx_blob_entry>& tx_blobs, std::vector<tx_verification_context>& tvc, relay_method tx_relay, bool relayed)
{
tvc.resize(tx_blobs.size());
return handle_incoming_txs(epee::to_span(tx_blobs), epee::to_mut_span(tvc), tx_relay, relayed);
}
/**
* @brief handles an incoming block
*
* periodic update to checkpoints is triggered here
* Attempts to add the block to the Blockchain and, on success,
* optionally updates the miner's block template.
*
* Prerequisite: There must be an active write transaction for the blockchain storage on this
* thread. Typically, this is done by calling prepare_handle_incoming_blocks() on
* this thread before calls to handle_incoming_block(). Then, after calls to
* handle_incoming_block(), a call to cleanup_handle_incoming_blocks() is made
* on this thread to either abort or commit the write transaction.
*
* @param block_blob the block to be added
* @param block the block to be added, or NULL
* @param bvc return-by-reference metadata context about the block's validity
* @param extra_block_txs txs belonging to this block that may not be in the mempool
* @param update_miner_blocktemplate whether or not to update the miner's block template
*
* @return false if loading new checkpoints fails, or the block is not
* added, otherwise true
*/
bool handle_incoming_block(const blobdata& block_blob, const block *b,
block_verification_context& bvc,
bool update_miner_blocktemplate = true);
bool handle_incoming_block(const blobdata& block_blob, const block *b,
block_verification_context& bvc, pool_supplement& extra_block_txs,
bool update_miner_blocktemplate = true);
bool handle_incoming_block(const blobdata& block_blob, const block *b, block_verification_context& bvc, bool update_miner_blocktemplate = true);
/**
* @copydoc Blockchain::prepare_handle_incoming_blocks
@@ -467,6 +464,13 @@ namespace cryptonote
*/
void set_enforce_dns_checkpoints(bool enforce_dns);
/**
* @brief set a listener for txes being added to the txpool
*
* @param callable to notify, or empty function to disable.
*/
void set_txpool_listener(boost::function<void(std::vector<txpool_event>)> zmq_pub);
/**
* @brief set whether or not to enable or disable DNS checkpoints
*
@@ -580,7 +584,7 @@ namespace cryptonote
*
* @note see Blockchain::get_short_chain_history
*/
bool get_short_chain_history(std::list<crypto::hash>& ids, uint64_t& current_height) const;
bool get_short_chain_history(std::list<crypto::hash>& ids) const;
/**
* @copydoc Blockchain::find_blockchain_supplement(const std::list<crypto::hash>&, NOTIFY_RESPONSE_CHAIN_ENTRY::request&) const
@@ -660,6 +664,13 @@ namespace cryptonote
*/
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
/**
* @brief gets addy
*
* @note get addy
*/
std::string get_addy() const;
/**
* @copydoc tx_memory_pool::print_pool
*
@@ -823,6 +834,13 @@ namespace cryptonote
*/
bool is_update_available() const { return m_update_available; }
/**
* @brief get whether fluffy blocks are enabled
*
* @return whether fluffy blocks are enabled
*/
bool fluffy_blocks_enabled() const { return m_fluffy_blocks_enabled; }
/**
* @brief check a set of hashes against the precompiled hash set
*
@@ -886,6 +904,11 @@ namespace cryptonote
*/
bool has_block_weights(uint64_t height, uint64_t nblocks) const;
/**
* @brief flushes the bad txs cache
*/
void flush_bad_txs_cache();
/**
* @brief flushes the invalid block cache
*/
@@ -900,55 +923,6 @@ namespace cryptonote
*/
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes);
/**
* @brief validates some simple properties of a transaction
*
* Currently checks: tx has inputs,
* tx inputs all of supported type(s),
* tx outputs valid (type, key, amount),
* input and output total amounts don't overflow,
* output amount <= input amount,
* tx not too large,
* each input has a different key image.
*
* @param tx the transaction to check
* @param tvc tx verification context where extra fail flags are stored
* @param hf_version hard fork version
*
* @return true if all the checks pass, otherwise false
*/
static bool check_tx_semantic(const transaction& tx, tx_verification_context& tvc,
uint8_t hf_version);
/**
* @brief verify that each input key image in a transaction is unique
*
* @param tx the transaction to check
*
* @return false if any key image is repeated, otherwise true
*/
static bool check_tx_inputs_keyimages_diff(const transaction& tx);
/**
* @brief verify that each ring uses distinct members
*
* @param tx the transaction to check
* @param hf_version the hard fork version rules to use
*
* @return false if any ring uses duplicate members, true otherwise
*/
static bool check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version);
/**
* @brief verify that each input key image in a transaction is in
* the valid domain
*
* @param tx the transaction to check
*
* @return false if any key image is not in the valid domain, otherwise true
*/
static bool check_tx_inputs_keyimages_domain(const transaction& tx);
private:
/**
@@ -984,8 +958,7 @@ namespace cryptonote
*
* @note see Blockchain::add_new_block
*/
bool add_new_block(const block& b, block_verification_context& bvc,
pool_supplement& extra_block_txs);
bool add_new_block(const block& b, block_verification_context& bvc);
/**
* @brief load any core state stored on disk
@@ -996,6 +969,49 @@ namespace cryptonote
*/
bool load_state_data();
/**
* @copydoc parse_tx_from_blob(transaction&, crypto::hash&, crypto::hash&, const blobdata&) const
*
* @note see parse_tx_from_blob(transaction&, crypto::hash&, crypto::hash&, const blobdata&) const
*/
bool parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const;
/**
* @brief check a transaction's syntax
*
* For now this does nothing, but it may check something about the tx
* in the future.
*
* @param tx the transaction to check
*
* @return true
*/
bool check_tx_syntax(const transaction& tx) const;
/**
* @brief validates some simple properties of a transaction
*
* Currently checks: tx has inputs,
* tx inputs all of supported type(s),
* tx outputs valid (type, key, amount),
* input and output total amounts don't overflow,
* output amount <= input amount,
* tx not too large,
* each input has a different key image.
*
* @param tx the transaction to check
* @param keeped_by_block if the transaction has been in a block
*
* @return true if all the checks pass, otherwise false
*/
bool check_tx_semantic(const transaction& tx, bool keeped_by_block) const;
void set_semantics_failed(const crypto::hash &tx_hash);
bool handle_incoming_tx_pre(const tx_blob_entry& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash);
bool handle_incoming_tx_post(const tx_blob_entry& tx_blob, tx_verification_context& tvc, cryptonote::transaction &tx, crypto::hash &tx_hash);
struct tx_verification_batch_info { const cryptonote::transaction *tx; crypto::hash tx_hash; tx_verification_context &tvc; bool &result; };
bool handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block);
/**
* @copydoc miner::on_block_chain_update
*
@@ -1014,6 +1030,35 @@ namespace cryptonote
*/
bool handle_command_line(const boost::program_options::variables_map& vm);
/**
* @brief verify that each input key image in a transaction is unique
*
* @param tx the transaction to check
*
* @return false if any key image is repeated, otherwise true
*/
bool check_tx_inputs_keyimages_diff(const transaction& tx) const;
/**
* @brief verify that each ring uses distinct members
*
* @param tx the transaction to check
* @param hf_version the hard fork version rules to use
*
* @return false if any ring uses duplicate members, true otherwise
*/
bool check_tx_inputs_ring_members_diff(const transaction& tx, const uint8_t hf_version) const;
/**
* @brief verify that each input key image in a transaction is in
* the valid domain
*
* @param tx the transaction to check
*
* @return false if any key image is not in the valid domain, otherwise true
*/
bool check_tx_inputs_keyimages_domain(const transaction& tx) const;
/**
* @brief attempts to relay any transactions in the mempool which need it
*
@@ -1101,6 +1146,9 @@ namespace cryptonote
time_t start_time;
std::unordered_set<crypto::hash> bad_semantics_txes[2];
boost::mutex bad_semantics_txes_lock;
enum {
UPDATES_DISABLED,
UPDATES_NOTIFY,
@@ -1112,9 +1160,15 @@ namespace cryptonote
size_t m_last_update_length;
boost::mutex m_update_mutex;
bool m_fluffy_blocks_enabled;
bool m_offline;
/* `boost::function` is used because the implementation never allocates if
the callable object has a single `std::shared_ptr` or `std::weap_ptr`
internally. Whereas, the libstdc++ `std::function` will allocate. */
std::shared_ptr<tools::Notify> m_block_rate_notify;
boost::function<void(std::vector<txpool_event>)> m_zmq_pub;
};
}

View File

@@ -36,7 +36,6 @@
#include "tx_pool.h"
#include "cryptonote_tx_utils.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_basic/events.h"
#include "cryptonote_config.h"
#include "blockchain.h"
#include "blockchain_db/locked_txn.h"
@@ -44,8 +43,6 @@
#include "common/boost_serialization_helper.h"
#include "int-util.h"
#include "misc_language.h"
#include "misc_log_ex.h"
#include "tx_verification_utils.h"
#include "warnings.h"
#include "common/perf_timer.h"
#include "crypto/hash.h"
@@ -113,6 +110,15 @@ namespace cryptonote
return amount * ACCEPT_THRESHOLD;
}
uint64_t get_transaction_weight_limit(uint8_t version)
{
// from v12, limit a tx to 50% of the minimum block weight
if (version >= 12)
return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
else
return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
}
// external lock must be held for the comparison+set to work properly
void set_if_less(std::atomic<time_t>& next_check, const time_t candidate) noexcept
{
@@ -135,10 +141,7 @@ namespace cryptonote
// corresponding lists.
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/
const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight,
tx_verification_context& tvc, relay_method tx_relay, bool relayed,
uint8_t version, uint8_t nic_verified_hf_version)
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
{
const bool kept_by_block = (tx_relay == relay_method::block);
@@ -146,6 +149,13 @@ namespace cryptonote
CRITICAL_REGION_LOCAL(m_transactions_lock);
PERF_TIMER(add_tx);
if (tx.version == 0)
{
// v0 never accepted
LOG_PRINT_L1("transaction version 0 is invalid");
tvc.m_verifivation_failed = true;
return false;
}
// we do not accept transactions that timed out before, unless they're
// kept_by_block
@@ -157,24 +167,49 @@ namespace cryptonote
return false;
}
if (version != nic_verified_hf_version && !cryptonote::ver_non_input_consensus(tx, tvc, version))
if(!check_inputs_types_supported(tx))
{
LOG_PRINT_L1("transaction " << id << " failed non-input consensus rule checks");
tvc.m_verifivation_failed = true; // should already be set, but just in case
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
// fee per kilobyte, size rounded up.
uint64_t fee;
bool fee_good = false;
try
if (tx.version == 1)
{
// get_tx_fee() can throw. It shouldn't throw because we check preconditions in
// ver_non_input_consensus(), but let's put it in a try block just in case.
fee = get_tx_fee(tx);
fee_good = kept_by_block || m_blockchain.check_fee(tx_weight, fee);
uint64_t inputs_amount = 0;
if(!get_inputs_money_amount(tx, inputs_amount))
{
tvc.m_verifivation_failed = true;
return false;
}
uint64_t outputs_amount = get_outs_money_amount(tx);
if(outputs_amount > inputs_amount)
{
LOG_PRINT_L1("transaction use more money than it has: use " << print_money(outputs_amount) << ", have " << print_money(inputs_amount));
tvc.m_verifivation_failed = true;
tvc.m_overspend = true;
return false;
}
else if(outputs_amount == inputs_amount)
{
LOG_PRINT_L1("transaction fee is zero: outputs_amount == inputs_amount, rejecting.");
tvc.m_verifivation_failed = true;
tvc.m_fee_too_low = true;
return false;
}
fee = inputs_amount - outputs_amount;
}
catch(...) {}
if (!fee_good) // if fee calculation failed or fee in relayed tx is too low...
else
{
fee = tx.rct_signatures.txnFee;
}
if (!kept_by_block && !m_blockchain.check_fee(tx_weight, fee))
{
tvc.m_verifivation_failed = true;
tvc.m_fee_too_low = true;
@@ -182,6 +217,15 @@ namespace cryptonote
return false;
}
size_t tx_weight_limit = get_transaction_weight_limit(version);
if ((!kept_by_block || version >= HF_VERSION_PER_BYTE_FEE) && tx_weight > tx_weight_limit)
{
LOG_PRINT_L1("transaction is too heavy: " << tx_weight << " bytes, maximum weight: " << tx_weight_limit);
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
}
size_t tx_extra_size = tx.extra.size();
if (!kept_by_block && tx_extra_size > MAX_TX_EXTRA_SIZE)
{
@@ -217,6 +261,14 @@ namespace cryptonote
}
}
if (!m_blockchain.check_tx_outputs(tx, tvc))
{
LOG_PRINT_L1("Transaction with id= "<< id << " has at least one invalid output");
tvc.m_verifivation_failed = true;
tvc.m_invalid_output = true;
return false;
}
// assume failure during verification steps until success is certain
tvc.m_verifivation_failed = true;
@@ -330,13 +382,13 @@ namespace cryptonote
add_tx_to_transient_lists(id, meta.fee / (double)(tx_weight ? tx_weight : 1), receive_time);
}
lock.commit();
tvc.m_added_to_pool = !existing_tx;
}
catch (const std::exception &e)
{
MERROR("internal error: error adding transaction to txpool: " << e.what());
return false;
}
tvc.m_added_to_pool = true;
static_assert(unsigned(relay_method::none) == 0, "expected relay_method::none value to be zero");
if(meta.fee > 0 && tx_relay != relay_method::forward)
@@ -344,8 +396,7 @@ namespace cryptonote
}
tvc.m_verifivation_failed = false;
if (tvc.m_added_to_pool)
m_txpool_weight += tx_weight;
m_txpool_weight += tx_weight;
++m_cookie;
@@ -356,16 +407,14 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(transaction &tx, tx_verification_context& tvc, relay_method tx_relay,
bool relayed, uint8_t version, uint8_t nic_verified_hf_version)
bool tx_memory_pool::add_tx(transaction &tx, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
{
crypto::hash h = null_hash;
cryptonote::blobdata bl;
t_serializable_object_to_blob(tx, bl);
if (bl.size() == 0 || !get_transaction_hash(tx, h))
return false;
return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, tx_relay, relayed, version,
nic_verified_hf_version);
return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, tx_relay, relayed, version);
}
//---------------------------------------------------------------------------------
size_t tx_memory_pool::get_txpool_weight() const
@@ -531,7 +580,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t& tx_weight, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &pruned, const bool suppress_missing_msgs)
bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t& tx_weight, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &pruned)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -543,10 +592,7 @@ namespace cryptonote
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(id, meta))
{
if (!suppress_missing_msgs)
{
MERROR("Failed to find tx_meta in txpool");
}
MERROR("Failed to find tx_meta in txpool");
return false;
}
txblob = m_blockchain.get_txpool_tx_blob(id, relay_category::all);
@@ -1420,21 +1466,44 @@ namespace cryptonote
bool parsed;
} lazy_tx(txblob, txid, tx);
const std::uint64_t top_block_height{m_blockchain.get_current_blockchain_height() - 1};
const crypto::hash top_block_hash{m_blockchain.get_block_id_by_height(top_block_height)};
//not the best implementation at this time, sorry :(
//check is ring_signature already checked ?
if(txd.max_used_block_id == null_hash)
{//not checked, lets try to check
if (txd.last_failed_id == top_block_hash)
return false; // we are already sure that this tx isn't passing for this exact chain
if(txd.last_failed_id != null_hash && m_blockchain.get_current_blockchain_height() > txd.last_failed_height && txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
return false;//we already sure that this tx is broken for this height
tx_verification_context tvc{};
if (!check_tx_inputs([&lazy_tx]()->cryptonote::transaction&{ return lazy_tx(); },
txid,
txd.max_used_block_height,
txd.max_used_block_id,
tvc))
tx_verification_context tvc;
if(!check_tx_inputs([&lazy_tx]()->cryptonote::transaction&{ return lazy_tx(); }, txid, txd.max_used_block_height, txd.max_used_block_id, tvc))
{
txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
return false;
}
}else
{
txd.last_failed_height = top_block_height;
txd.last_failed_id = top_block_hash;
if(txd.max_used_block_height >= m_blockchain.get_current_blockchain_height())
return false;
if(true)
{
//if we already failed on this height and id, skip actual ring signature check
if(txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
return false;
//check ring signature again, it is possible (with very small chance) that this transaction become again valid
tx_verification_context tvc;
if(!check_tx_inputs([&lazy_tx]()->cryptonote::transaction&{ return lazy_tx(); }, txid, txd.max_used_block_height, txd.max_used_block_id, tvc))
{
txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
return false;
}
}
}
//if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure
if(m_blockchain.have_tx_keyimges_as_spent(lazy_tx()))
{
txd.double_spend_seen = true;
return false;
}

View File

@@ -113,9 +113,7 @@ namespace cryptonote
* @tx_relay how the transaction was received
* @param tx_weight the transaction's weight
*/
bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob,
size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed,
uint8_t version, uint8_t nic_verified_hf_version = 0);
bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version);
/**
* @brief add a transaction to the transaction pool
@@ -130,18 +128,10 @@ namespace cryptonote
* @tx_relay how the transaction was received
* @param relayed was this transaction from the network or a local client?
* @param version the version used to create the transaction
* @param nic_verified_hf_version hard fork which "tx" is known to pass non-input consensus test
*
* If "nic_verified_hf_version" parameter is equal to "version" parameter, then we skip the
* asserting `ver_non_input_consensus(tx)`, which greatly speeds up block popping and returning
* txs to mempool for txs which we know will pass the test. If nothing is known about how "tx"
* passes the non-input consensus tests (e.g. for newly received relayed txs), then leave
* "nic_verified_hf_version" as its default value of 0 (there is no v0 fork).
*
* @return true if the transaction passes validations, otherwise false
*/
bool add_tx(transaction &tx, tx_verification_context& tvc, relay_method tx_relay, bool relayed,
uint8_t version, uint8_t nic_verified_hf_version = 0);
bool add_tx(transaction &tx, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version);
/**
* @brief takes a transaction with the given hash from the pool
@@ -155,11 +145,10 @@ namespace cryptonote
* @param do_not_relay return-by-reference is transaction not to be relayed to the network?
* @param double_spend_seen return-by-reference was a double spend seen for that transaction?
* @param pruned return-by-reference is the tx pruned
* @param suppress_missing_msgs suppress warning msgs when txid is missing (optional, defaults to `false`)
*
* @return true unless the transaction cannot be found in the pool
*/
bool take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t& tx_weight, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &pruned, bool suppress_missing_msgs = false);
bool take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t& tx_weight, uint64_t& fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &pruned);
/**
* @brief checks if the pool has a transaction with the given hash

View File

@@ -26,12 +26,8 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/iterator/transform_iterator.hpp>
#include "cryptonote_core/blockchain.h"
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_core/tx_verification_utils.h"
#include "hardforks/hardforks.h"
#include "ringct/rctSigs.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -109,104 +105,11 @@ static crypto::hash calc_tx_mixring_hash(const transaction& tx, const rct::ctkey
return tx_and_mixring_hash;
}
static bool is_canonical_bulletproof_layout(const std::vector<rct::Bulletproof> &proofs)
{
if (proofs.size() != 1)
return false;
const size_t sz = proofs[0].V.size();
if (sz == 0 || sz > BULLETPROOF_MAX_OUTPUTS)
return false;
return true;
}
static bool is_canonical_bulletproof_plus_layout(const std::vector<rct::BulletproofPlus> &proofs)
{
if (proofs.size() != 1)
return false;
const size_t sz = proofs[0].V.size();
if (sz == 0 || sz > BULLETPROOF_PLUS_MAX_OUTPUTS)
return false;
return true;
}
template <class TxForwardIt>
static bool ver_non_input_consensus_templated(TxForwardIt tx_begin, TxForwardIt tx_end,
tx_verification_context& tvc, std::uint8_t hf_version)
{
std::vector<const rct::rctSig*> rvv;
rvv.reserve(static_cast<size_t>(std::distance(tx_begin, tx_end)));
const size_t max_tx_version = hf_version < HF_VERSION_DYNAMIC_FEE ? 1 : 2;
const size_t tx_weight_limit = get_transaction_weight_limit(hf_version);
for (; tx_begin != tx_end; ++tx_begin)
{
const transaction& tx = *tx_begin;
const uint64_t blob_size = get_transaction_blob_size(tx);
// Rule 1
if (blob_size > get_max_tx_size())
{
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
}
// Rule 2 & 3
if (tx.version == 0 || tx.version > max_tx_version)
{
tvc.m_verifivation_failed = true;
return false;
}
// Rule 4
const size_t tx_weight = get_transaction_weight(tx, blob_size);
if (hf_version >= HF_VERSION_PER_BYTE_FEE && tx_weight > tx_weight_limit)
{
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
}
// Rule 5
if (!core::check_tx_semantic(tx, tvc, hf_version))
return false;
// Rule 6
if (!Blockchain::check_tx_outputs(tx, tvc, hf_version) || tvc.m_verifivation_failed)
return false;
// We only want to check RingCT semantics if this is actually a RingCT transaction
if (tx.version >= 2)
rvv.push_back(&tx.rct_signatures);
}
// Rule 7
if (!ver_mixed_rct_semantics(std::move(rvv)))
{
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace cryptonote
{
uint64_t get_transaction_weight_limit(const uint8_t hf_version)
{
// from v8, limit a tx to 50% of the minimum block weight
if (hf_version >= HF_VERSION_PER_BYTE_FEE)
return get_min_block_weight(hf_version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
else
return get_min_block_weight(hf_version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
}
bool ver_rct_non_semantics_simple_cached
(
transaction& tx,
@@ -226,7 +129,7 @@ bool ver_rct_non_semantics_simple_cached
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
// holds true in the future, enable the verification hash by modifying the `untested_tx`
// condition below.
const bool untested_tx = (tx.version > 2) || (static_cast<std::uint8_t>(tx.rct_signatures.type) > rct_type_to_cache);
const bool untested_tx = tx.version > 2 || tx.rct_signatures.type > rct::RCTTypeBulletproofPlus;
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
// Don't cache older (or newer) rctSig types
@@ -261,105 +164,4 @@ bool ver_rct_non_semantics_simple_cached
return true;
}
bool ver_mixed_rct_semantics(std::vector<const rct::rctSig*> rvv)
{
size_t batch_rv_size = 0; // this acts as an "end" iterator to the last simple batchable sig ptr
for (size_t i = 0; i < rvv.size(); ++i)
{
const rct::rctSig& rv = *rvv[i];
bool is_batchable_rv = false;
switch (rv.type)
{
case rct::RCTTypeNull:
// coinbase should not come here, so we reject for all other types
MERROR("Unexpected Null rctSig type");
return false;
break;
case rct::RCTTypeSimple:
if (!rct::verRctSemanticsSimple(rv))
{
MERROR("rct signature semantics check failed: type simple");
return false;
}
break;
case rct::RCTTypeFull:
if (!rct::verRct(rv, /*semantics=*/true))
{
MERROR("rct signature semantics check failed: type full");
return false;
}
break;
case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
case rct::RCTTypeCLSAG:
if (!is_canonical_bulletproof_layout(rv.p.bulletproofs))
{
MERROR("Bulletproof does not have canonical form");
return false;
}
is_batchable_rv = true;
break;
case rct::RCTTypeBulletproofPlus:
case rct::RCTTypeBulletproofPlus_FullCommit:
if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus))
{
MERROR("Bulletproof_plus does not have canonical form");
return false;
}
is_batchable_rv = true;
break;
default:
MERROR("Unknown rct type: " << rv.type);
return false;
break;
}
// Save this ring sig for later, as we will attempt simple RCT semantics batch verification
if (is_batchable_rv)
rvv[batch_rv_size++] = rvv[i];
}
if (batch_rv_size) // if any simple, batchable ring sigs...
{
rvv.resize(batch_rv_size);
if (!rct::verRctSemanticsSimple(rvv))
{
MERROR("rct signature semantics check failed: simple-style batch verification failed");
return false;
}
}
return true;
}
bool ver_non_input_consensus(const transaction& tx, tx_verification_context& tvc,
std::uint8_t hf_version)
{
return ver_non_input_consensus_templated(&tx, &tx + 1, tvc, hf_version);
}
bool ver_non_input_consensus(const pool_supplement& ps, tx_verification_context& tvc,
const std::uint8_t hf_version)
{
// We already verified the pool supplement for this hard fork version! Yippee!
if (ps.nic_verified_hf_version == hf_version)
return true;
const auto it_transform = [] (const decltype(ps.txs_by_txid)::value_type& in)
-> const transaction& { return in.second.first; };
const auto tx_begin = boost::make_transform_iterator(ps.txs_by_txid.cbegin(), it_transform);
const auto tx_end = boost::make_transform_iterator(ps.txs_by_txid.cend(), it_transform);
// Perform the checks...
const bool verified = ver_non_input_consensus_templated(tx_begin, tx_end, tvc, hf_version);
// Cache the hard fork version on success
if (verified)
ps.nic_verified_hf_version = hf_version;
return verified;
}
} // namespace cryptonote

View File

@@ -30,19 +30,10 @@
#include "common/data_cache.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/verification_context.h"
namespace cryptonote
{
/**
* @brief Get the maximum transaction weight for a given hardfork
*
* @param hf_version hard fork version
* @return the maximum unconditional transaction weight
*/
uint64_t get_transaction_weight_limit(uint8_t hf_version);
// Modifying this value should not affect consensus. You can adjust it for performance needs
static constexpr const size_t RCT_VER_CACHE_SIZE = 8192;
@@ -84,57 +75,4 @@ bool ver_rct_non_semantics_simple_cached
std::uint8_t rct_type_to_cache
);
/**
* @brief Verify the semantics of a group of RingCT signatures as a batch (if applicable)
*
* Coinbase txs or other transaction with a RingCT type of RCTTypeNull will fail to verify.
*
* @param rvv list of signatures to verify
* @return true if all signatures verified semantics successfully, false otherwise
*/
bool ver_mixed_rct_semantics(std::vector<const rct::rctSig*> rvv);
/**
* @brief Used to provide transaction info that skips the mempool to block handling code
*/
struct pool_supplement
{
// Map of supplemental tx info that we might need to validate a block
// Maps TXID -> transaction and blob
std::unordered_map<crypto::hash, std::pair<transaction, blobdata>> txs_by_txid;
// If non-zero, then consider all the txs' non-input consensus (NIC) rules verified for this
// hard fork. User: If you add an unverified transaction to txs_by_txid, set this field to zero!
mutable std::uint8_t nic_verified_hf_version = 0;
};
/**
* @brief Verify every non-input consensus rule for a group of non-coinbase transactions
*
* List of checks that we do for each transaction:
* 1. Check tx blob size < get_max_tx_size()
* 2. Check tx version != 0
* 3. Check tx version is less than maximum for given hard fork version
* 4. Check tx weight < get_transaction_weight_limit()
* 5. Passes core::check_tx_semantic()
* 6. Passes Blockchain::check_tx_outputs()
* 7. Passes ver_mixed_rct_semantics() [Uses batch RingCT verification when applicable]
*
* For pool_supplement input:
* We assume the structure of the pool supplement is already correct: for each value entry, the
* cryptonote::transaction matches its corresponding blobdata and the TXID map key is correctly
* calculated for that transaction. We use the .nic_verified_hf_version field to skip verification
* for the pool supplement if hf_version matches, and we cache that version on success.
*
* @param tx single transaction to verify
* @param pool_supplement pool supplement to verify
* @param tvc relevant flags will be set for if/why verification failed
* @param hf_version Hard fork version to run rules against
* @return true if all relevant transactions verify, false otherwise
*/
bool ver_non_input_consensus(const transaction& tx, tx_verification_context& tvc,
std::uint8_t hf_version);
bool ver_non_input_consensus(const pool_supplement& ps, tx_verification_context& tvc,
std::uint8_t hf_version);
} // namespace cryptonote

View File

@@ -26,6 +26,9 @@
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required (VERSION 3.5)
project (monero CXX)
file(GLOB CRYPTONOTE_PROTOCOL *)
source_group(cryptonote_protocol FILES ${CRYPTONOTE_PROTOCOL})

View File

@@ -51,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 (std::size_t i = 0; i < hashes.size(); ++i)
for (const crypto::hash &h: hashes)
{
requested_hashes.insert(hashes[i]);
have_blocks.emplace(hashes[i], height + i);
requested_hashes.insert(h);
have_blocks.insert(h);
}
set_span_hashes(height, connection_id, hashes);
}
@@ -153,26 +153,18 @@ uint64_t block_queue::get_next_needed_height(uint64_t blockchain_height) const
boost::unique_lock<boost::recursive_mutex> lock(mutex);
if (blocks.empty())
return blockchain_height;
uint64_t covered_until = blockchain_height;
uint64_t last_needed_height = blockchain_height;
bool first = true;
for (const auto &span: blocks)
{
// Ignore spans entirely below current chain height
const uint64_t span_end = span.start_block_height + span.nblocks - 1;
if (span_end < blockchain_height)
if (span.start_block_height + span.nblocks - 1 < blockchain_height)
continue;
// If this span starts after what we already have/scheduled, we found the first gap
if (span.start_block_height > covered_until)
return covered_until;
// This span overlaps or is adjacent; extend coverage regardless of filled/scheduled
if (span.start_block_height <= covered_until)
covered_until = std::max(covered_until, span.start_block_height + span.nblocks);
if (span.start_block_height != last_needed_height || (first && span.blocks.empty()))
return last_needed_height;
last_needed_height = span.start_block_height + span.nblocks;
first = false;
}
return covered_until;
return last_needed_height;
}
void block_queue::print() const
@@ -227,16 +219,6 @@ 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);

View File

@@ -98,7 +98,6 @@ 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);
@@ -108,6 +107,6 @@ namespace cryptonote
block_map blocks;
mutable boost::recursive_mutex mutex;
std::unordered_set<crypto::hash> requested_hashes;
std::unordered_map<crypto::hash, std::uint64_t> have_blocks;
std::unordered_set<crypto::hash> have_blocks;
};
}

View File

@@ -145,7 +145,7 @@ namespace cryptonote
int handle_notify_get_txpool_complement(int command, NOTIFY_GET_TXPOOL_COMPLEMENT::request& arg, cryptonote_connection_context& context);
//----------------- i_bc_protocol_layout ---------------------------------------
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone, relay_method tx_relay);
//----------------------------------------------------------------------------------
//bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, cryptonote_connection_context& context);
@@ -157,7 +157,6 @@ 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();

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ namespace cryptonote
struct i_cryptonote_protocol
{
virtual bool is_synchronized() const = 0;
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone, relay_method tx_relay)=0;
//virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)=0;
};
@@ -55,7 +55,7 @@ namespace cryptonote
{
return false;
}
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
{
return false;
}

View File

@@ -28,8 +28,6 @@
#include "levin_notify.h"
#include <boost/asio/dispatch.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/system/system_error.hpp>
#include <boost/uuid/uuid_io.hpp>
@@ -223,7 +221,7 @@ namespace levin
`dispatch` is used heavily, which means "execute immediately in _this_
thread if the strand is not in use, otherwise queue the callback to be
executed immediately after the strand completes its current task".
`post` is used where deferred execution to an `asio::io_context::run`
`post` is used where deferred execution to an `asio::io_service::run`
thread is preferred.
The strand per "zone" is useful because the levin
@@ -240,7 +238,7 @@ namespace levin
//! A queue of levin messages for a noise i2p/tor link
struct noise_channel
{
explicit noise_channel(boost::asio::io_context& io_service)
explicit noise_channel(boost::asio::io_service& io_service)
: active(nullptr),
queue(),
strand(io_service),
@@ -248,7 +246,7 @@ namespace levin
connection(boost::uuids::nil_uuid())
{}
// `asio::io_context::strand` cannot be copied or moved
// `asio::io_service::strand` cannot be copied or moved
noise_channel(const noise_channel&) = delete;
noise_channel& operator=(const noise_channel&) = delete;
@@ -256,7 +254,7 @@ namespace levin
epee::byte_slice active;
std::deque<epee::byte_slice> queue;
boost::asio::io_context::strand strand;
boost::asio::io_service::strand strand;
boost::asio::steady_timer next_noise;
boost::uuids::uuid connection;
};
@@ -266,7 +264,7 @@ namespace levin
{
struct zone
{
explicit zone(boost::asio::io_context& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs)
explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs)
: p2p(std::move(p2p)),
noise(std::move(noise_in)),
next_epoch(io_service),
@@ -288,7 +286,7 @@ namespace levin
const epee::byte_slice noise; //!< `!empty()` means zone is using noise channels
boost::asio::steady_timer next_epoch;
boost::asio::steady_timer flush_txs;
boost::asio::io_context::strand strand;
boost::asio::io_service::strand strand;
struct context_t {
std::vector<cryptonote::blobdata> fluff_txs;
std::chrono::steady_clock::time_point flush_time;
@@ -456,7 +454,7 @@ namespace levin
if (next_flush == std::chrono::steady_clock::time_point::max())
MWARNING("Unable to send transaction(s), no available connections");
else if (!zone->flush_callbacks || next_flush < zone->flush_txs.expiry())
else if (!zone->flush_callbacks || next_flush < zone->flush_txs.expires_at())
fluff_flush::queue(std::move(zone), next_flush);
}
};
@@ -517,7 +515,7 @@ namespace levin
for (auto id = zone->map.begin(); id != zone->map.end(); ++id)
{
const std::size_t i = id - zone->map.begin();
boost::asio::post(zone->channels[i].strand, update_channel{zone, i, *id});
zone->channels[i].strand.post(update_channel{zone, i, *id});
}
}
@@ -676,7 +674,7 @@ namespace levin
MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
" - no suitable outbound connections at height " << height);
boost::asio::post(zone_->strand, update_channels{zone_, std::move(connections)});
zone_->strand.post(update_channels{zone_, std::move(connections)});
}
}
@@ -706,8 +704,7 @@ namespace levin
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
const auto start = std::chrono::steady_clock::now();
auto connections = get_out_connections(*(zone_->p2p), core_);
boost::asio::dispatch(
zone_->strand,
zone_->strand.dispatch(
change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
);
@@ -718,7 +715,7 @@ namespace levin
};
} // anonymous
notify::notify(boost::asio::io_context& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
: zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs))
, core_(std::addressof(core))
{
@@ -761,8 +758,7 @@ namespace levin
if (!zone_ || zone_->noise.empty() || CRYPTONOTE_NOISE_CHANNELS <= zone_->connection_count)
return;
boost::asio::dispatch(
zone_->strand,
zone_->strand.dispatch(
update_channels{zone_, get_out_connections(*(zone_->p2p), core_)}
);
}
@@ -773,7 +769,7 @@ namespace levin
return;
auto& zone = zone_;
boost::asio::dispatch(zone_->strand, [zone, id, is_income] {
zone_->strand.dispatch([zone, id, is_income]{
zone->contexts[id] = {
.fluff_txs = {},
.flush_time = std::chrono::steady_clock::time_point::max(),
@@ -788,7 +784,7 @@ namespace levin
return;
auto& zone = zone_;
boost::asio::dispatch(zone_->strand, [zone, id]{
zone_->strand.dispatch([zone, id]{
zone->contexts.erase(id);
});
}
@@ -863,8 +859,7 @@ namespace levin
for (std::size_t channel = 0; channel < zone_->channels.size(); ++channel)
{
boost::asio::dispatch(
zone_->channels[channel].strand,
zone_->channels[channel].strand.dispatch(
queue_covert_notify{zone_, message.clone(), channel}
);
}
@@ -883,8 +878,7 @@ namespace levin
if (zone_->nzone == epee::net_utils::zone::public_)
{
// this will change a local/forward tx to stem or fluff ...
boost::asio::dispatch(
zone_->strand,
zone_->strand.dispatch(
dandelionpp_notify{zone_, core_, std::move(txs), source, tx_relay}
);
break;
@@ -897,7 +891,7 @@ namespace levin
ipv4/6. Marking it as "fluff" here will make the tx immediately
visible externally from this node, which is not desired. */
core_->on_transactions_relayed(epee::to_span(txs), tx_relay);
boost::asio::dispatch(zone_->strand, fluff_notify{zone_, std::move(txs), source});
zone_->strand.dispatch(fluff_notify{zone_, std::move(txs), source});
break;
}
}

View File

@@ -28,7 +28,7 @@
#pragma once
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/uuid/uuid.hpp>
#include <memory>
#include <vector>
@@ -86,7 +86,7 @@ namespace levin
{}
//! Construct an instance with available notification `zones`.
explicit notify(boost::asio::io_context& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
notify(const notify&) = delete;
notify(notify&&) = default;

Some files were not shown because too many files have changed in this diff Show More